前言

工欲善其事,必先利其器。经过多次的重复配置 ubuntu 开发坏境,我终于决定花点时间总结一下,并将其写成一个自动化配置脚本。服务器实例:ubuntu 16.04,技术栈:shell,python。

1. 主机名

可以通过 hostname newname 修改主机名,不过最好是写入 /etc/hostname 文件,重启生效。为了让同一内网段的主机可以通过主机名访问,应在 /etc/hosts 中添加私有ip的解析。

2. 命令提示符

与命令提示符相关的环境变量是 PS1,初始值为:PS1='\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$',各字符解释如下:

#\u:当前登陆用户名
#\h:当前主机名(如 ubuntu)
#\H:当前主机的域名全称(ubuntu.ubuntu.com)
#\w:当前目录(绝对路径)
#\W:当前目录的 basename(只显示最后一级路径)
#\$:一般用户为$,root 用户为#
#\t:当前时间(24小时制,HH:MM:SS)
#\T:当前时间(12小时)
#\@:当前时间(Am/PM)
#\d:当前日期
#\v:Bash 版本
#\V:Bash 的发布版本号
#\S:Shell 名称

对于我来说我只需要 \u、\h、\W(\w 如果多进几个目录敲命令的体验就很差了),为了让命令行一目了然,最好给命令提示符加个颜色 PS1='${debian_chroot:+($debian_chroot)}\[\e[1;32m\]\u@\h\[\e[0m\]:\[\e[1;34m\]\W\[\e[0m\]\$ ',颜色代码解释如下:

前景色 背景色 效果
30m 40;
31m 41;
32m 42; 绿
33m 43;
34m 44;
35m 45;
36m 46; 天蓝
37m 47;
#\033[背景;字体颜色m或者\e[背景;字体颜色m

#0   重新设置属性到缺省设置
#1 设置粗体
#2 设置一半亮度(模拟彩色显示器的颜色)
#4 设置下划线(模拟彩色显示器的颜色)
#5 设置闪烁
#7 设置反向图象
#22 设置一般密度
#24 关闭下划线
#25 关闭闪烁
#27 关闭反向图象

3. GNU Readline Library

Readline 的解释:从终端获取用户输入的字符流,辩认其中一些特定的字符序列,然后执行这些序列对应的函数或者宏。通俗一点讲就是绑定热键,比如在 bash 中默认按下 ctrl+a 执行的是光标回到行首的命令。

此处我需要优化的是:1、Tab 补全时忽略大小写;2、通过 ↑↓ 查询已输入关键字的历史记录。

vim ~/.inputrc

"\e[A": history-search-backward
"\e[B": history-search-forward # auto complete ignoring case
set show-all-if-ambiguous on
set completion-ignore-case on source ~/.inputrc

4. 历史记录

我需要:1、忽略重复的历史命令;2、保存更多的历史记录;3、忽略特定的历史记录;4、新建的终端同步 history。

export HISTCONTROL=ignoreboth # ignoreboth=ignoredups:ignorespace
export HISTSIZE=10000
export HISTFILESIZE=20000
export HISTIGNORE='pwd:ls' # make sure all terminals save history
shopt -s histappend
export PROMPT_COMMAND="history -a; $PROMPT_COMMAND"

5. Git 配置

想要流畅地使用 git,我认为有几点必须配置:

5.1 在命令提示符上显示 git 基本信息

安装完 git 之后,在 /etc/bash_completion.d 目录中会生成一个 git-prompt 文件:

if [[ -e /usr/lib/git-core/git-sh-prompt ]]; then
. /usr/lib/git-core/git-sh-prompt
fi

打开/usr/lib/git-core/git-sh-prompt,注释里面写了完整的操作步骤:

# To enable:
#
# 1) Copy this file to somewhere (e.g. ~/.git-prompt.sh).
# 2) Add the following line to your .bashrc/.zshrc:
# source ~/.git-prompt.sh
# 3a) Change your PS1 to call __git_ps1 as
# command-substitution:
# Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
# ZSH: setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
# the optional argument will be used as format string.
# 3b) Alternatively, for a slightly faster prompt, __git_ps1 can
# be used for PROMPT_COMMAND in Bash or for precmd() in Zsh
# with two parameters, <pre> and <post>, which are strings
# you would put in $PS1 before and after the status string
# generated by the git-prompt machinery. e.g.
# Bash: PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "'
# will show username, at-sign, host, colon, cwd, then
# various status string, followed by dollar and SP, as
# your prompt.
# ZSH: precmd () { __git_ps1 "%n" ":%~$ " "|%s" }
# will show username, pipe, then various status string,
# followed by colon, cwd, dollar and SP, as your prompt.
# Optionally, you can supply a third argument with a printf
# format string to finetune the output of the branch status
cp /usr/lib/git-core/git-sh-prompt .git-prompt.sh
source .git-prompt.sh
export PS1='${debian_chroot:+($debian_chroot)}\[\e[1;32m\]\u@\h\[\e[0m\]:\[\e[1;34m\]\W$(__git_ps1 " (%s)")\[\e[0m\]\$ '
export PROMPT_COMMAND='__git_ps1 "\[\e[1;32m\]\u@\h\[\e[0m\]:\[\e[1;34m\]\W\[\e[0m\]" "\$ "'

接下来还需赋值几个 git 环境变量让提示符显示更多 git 状态:

export GIT_PS1_SHOWDIRTYSTATE=true
export GIT_PS1_SHOWCOLORHINTS=true
export GIT_PS1_SHOWUNTRACKEDFILES=true
export GIT_PS1_SHOWUPSTREAM="auto" git config --global alias.lg "log --color --graph --pretty=format:'%C(yellow)%h%Creset%C(cyan)%C(bold)%C(red)%d%Creset %s %C(green)[%cn] %Creset%C(cyan)[%cd]%Creset' --date=format-local:'%m-%d %H:%M'"

显示效果:

5.2 多账号配置

我有两个 git 账号,分别是 gitee 和 github,且分别拥有各自的 name、email 和 ssh-key,我需要:

Ⅰ、两个账号都可以使用各自的密钥对免密码访问

生成密钥对:

# ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1] [-N new_passphrase] [-C comment] [-f output_keyfile]

ssh-keygen -t rsa -C "github@youclk.com" -f ~/.ssh/github/id_rsa -N ""
ssh-keygen -t rsa -C "gitee@youclk.com" -f ~/.ssh/gitee/id_rsa -N ""

编辑~/.ssh/config

Host     github.com
HostName github.com
User git
IdentityFile ~/.ssh/github/id_rsa
Host gitee.com
HostName gitee.com
User git
IdentityFile ~/.ssh/gitee/id_rsa

联通测试:

Ⅱ、 到达各自的仓库时自动切换用户名和邮箱

为了保证各仓库能够以正确的用户信息提交版本,需要取消全局的用户设置(我不理解为什么 global 中的用户信息要去覆盖各仓库的,反过来不是更好吗)。

git config --global --unset user.name
git config --global --unset user.emal

实现自动切换能想到的方案有很多,我更倾向于去修改 .git-prompt.sh,在 __git_ps1 () 函数末尾处增加一段逻辑:

if [ -z `git config user.name` ] && [ -z `git config user.email` ]; then
local git_remote=`git remote -v`
if [[ $git_remote =~ "github" ]]; then
`git config user.name "github" && git config user.email "github@youclk.com"`
elif [[ $git_remote =~ "gitee" ]]; then
`git config user.name "gitee" && git config user.email "gitee@youclk.com"`
fi
fi

顺带多提一下,git 默认忽略文件大小写,然而作为轻微的强迫症患者,我一定要和远程仓库保持完全一致:git config --global core.ignorecase false

6. 密钥对管理

我可能会一次性创建n台云服务器组成一个个集群,每个集群中有一个 leader 和 n 个 follower,follower 只是提供计算能力,它应该把自己全权交给 leader,那么在 leader 上必须能够访问所有的

follower。这时候统一密钥对管理就非常有必要了,只需要一个私钥就可以访问所有的服务器,其实上一节提到的 git 密钥对也可以一起管理。本节展开的话其实就是一些脚本实现,所以统一交给下一节归纳。

7. 自动配置脚本编写

现在我需要思考的是如何使用一行命令来自动完成以上所有的配置。由于配置中涉及到一些私钥等铭感信息,所以脚本必须放置于 git 私有库中,但是 ubuntu 初始化的时候并没有安装 git,所以还需要一个公有库来放置初始脚本,职能是安装 git 和访问私有库。最终我需要实现执行以下一行代码就完成整个 ubuntu 环境的配置:

# bash -c "$(curl -fsSL https://gitee.com/youclk/auto-config-entry/raw/master/centos/startup.sh)"
bash -c "$(curl -fsSL https://gitee.com/youclk/entry/raw/master/ubuntu/setting.sh)"

初始的入口脚本比较简单(安装 git,下载私有库并执行 python 脚本):

#!/bin/bash

apt update

# install git
if [ -z `which git` ]; then
apt install git
if [ ! $? -eq 0 ]; then exit 0; fi
fi # switch path to .auto_config
if [ ! -d ~/.auto_config ]; then
mkdir ~/.auto_config
if [ ! $? -eq 0 ]; then exit 0; fi
fi
cd ~/.auto_config # clone tools project
if [ ! -d "tools" ]; then
git clone https://gitee.com/youclk/tools.git
if [ ! $? -eq 0 ]; then exit 0; fi
fi
cd tools/ubuntu python3 setting.py rm -r ~/.auto_config

以下是 python 部分的结构:

代码比较简单,都是一些读写文件和结合系统命令的操作(步骤和说明都写在注释中了,不再赘述)。

setting.py

import os
import socket
import subprocess
import sys sys.path.append('../') from utility import host def edit_hostname():
"""
edit /etc/hostname and /etc/hosts
"""
old_hostname = socket.gethostname()
new_hostname = str.strip(input('please write a hostname:'))
if new_hostname and old_hostname != new_hostname:
subprocess.check_call(['hostname', new_hostname]) hostname_dir = '/etc/hostname'
hosts_dir = '/etc/hosts' # write hostname
with open(hostname_dir, 'w') as f:
f.write(new_hostname + '\n') # read hosts
with open(hosts_dir, 'r') as f:
hosts_lines = f.readlines() # write hosts
with open(hosts_dir, 'w') as f:
local_ip = host.get_local_ip()
n = 0
for i in range(0, len(hosts_lines)):
if local_ip in hosts_lines[i]:
hosts_lines[i] = hosts_lines[i].replace(old_hostname, new_hostname)
n += 1
if not n:
hosts_lines.append('\n' + local_ip + '\t' + new_hostname + '\n')
f.writelines(hosts_lines) def copy_config_files():
"""
configure git history readLine commandPrompt
"""
subprocess.check_call('cp -r bash_script/. ~/.', shell=True)
with open('/root/.bashrc', 'r+') as f:
bashrc = f.read()
if '.bashrc_pro' not in bashrc:
f.write('\nsource ~/.bashrc_pro.sh\n') def configure_ssh_key():
# copy ssk_key
subprocess.check_call('cp -r ssh_key/. ~/.ssh/.', shell=True)
# chmod
subprocess.check_call('chmod 400 ~/.ssh/*/id_rsa', shell=True) # configure git config
github_config = '''
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/git/id_rsa
'''
gitee_config = '''
Host gitee.com
HostName gitee.com
User git
IdentityFile ~/.ssh/git/id_rsa
''' if os.path.exists('/root/.ssh/config'):
with open('/root/.ssh/config', 'r+') as f:
git_config = f.read()
if 'github.com' not in git_config:
f.write(github_config)
elif 'gitee.com' not in git_config:
f.write(gitee_config)
else:
with open('/root/.ssh/config', 'w') as f:
f.write(github_config + gitee_config) if __name__ == '__main__':
if os.getuid() == 0:
edit_hostname()
copy_config_files()
configure_ssh_key()
print('success')
else:
print('please switch user => root')

host.py(一些可以公用的函数单独抽离出来):

import socket

def get_local_ip():
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as net:
net.connect(('8.8.8.8', 80))
return net.getsockname()[0]

.bashrc_pro.sh

#!/bin/bash

# config git

source .git_prompt.sh
export PS1='${debian_chroot:+($debian_chroot)}\[\e[1;32m\]\u@\h\[\e[0m\]:\[\e[1;34m\]\W$(__git_ps1 " (%s)")\[\e[0m\]\$ ' if [ "$(whoami)" == "root" ]; then
ps1_symbol="#"
else
ps1_symbol="$"
fi export PROMPT_COMMAND='__git_ps1 "\[\e[1;32m\]\u@\h\[\e[0m\]:\[\e[1;34m\]\W\[\e[0m\]" "$ps1_symbol "' export GIT_PS1_SHOWDIRTYSTATE=true
export GIT_PS1_SHOWCOLORHINTS=true
export GIT_PS1_SHOWUNTRACKEDFILES=true
export GIT_PS1_SHOWUPSTREAM="auto" # history export HISTCONTROL=ignoreboth # ignoreboth=ignoredups:ignorespace
export HISTSIZE=10000
export HISTFILESIZE=20000
export HISTIGNORE='pwd:ls' shopt -s histappend
export PROMPT_COMMAND="history -a; $PROMPT_COMMAND" # make sure all terminals save history # alias alias aliyun="ssh -i ~/.ssh/aliyun/id_rsa"

结语

终于剔除了一块疙瘩,以后一拿到服务器就可以愉快地玩耍了。当然,以上脚本只适合我个人的使用习惯,部分代码逻辑比较粗暴,各位看官参考和多多点赞就好,切勿直接使用,若有更好的想法,欢迎留言。


我的公众号《有刻》,我们共同成长!

Linux 小记 — Ubuntu 自动化配置的更多相关文章

  1. Linux小记 — Ubuntu自动化配置

    前言 工欲善其事,必先利其器.经过多次的重复配置ubuntu开发坏境,我终于决定花点时间总结一下,并将其写成一个自动化配置脚本.服务器实例:ubuntu 16.04,技术栈:shell,python. ...

  2. linux虚拟机Ubuntu命令配置

    # netstat -ntl  # 查看端口号,改成 0.0.0.0才能进行远程访问 # sudo service redis-server restart  # 修改后需要重启服务 python2和 ...

  3. Linux之Ubuntu环境配置(一)

    Linux下的搜狗输入法安装: 1.搜狗官网下载Linux64bit版本文件,默认在/home/username/Downloads目录下. 2.cd /home/username/Downloads ...

  4. 【Linux】-Ubuntu下配置JDK1.8

    前言 这次实在是不想写前言了,好吧,那咱就不写了. 内容 怀着复杂的心情来整理这个小小的操作,其实我的内心是拒绝的,因为太简单了,但是我却花费了很长的时间,有效时间花费了将近两个小时去整理这个小玩意儿 ...

  5. linux之ubuntu下php环境配置

    本文主要说明如何在Ubuntu下配置PHP开发环境LAMP.   Ubuntu 搭建 php 环境   所谓LAMP:Linux,Apache,Mysql,PHP   安装 Apache2:(注意可以 ...

  6. [Linux] PHP程序员玩转Linux系列-Ubuntu配置SVN服务器并搭配域名

    在线上部署网站的时候,大部分人是使用ftp,这样的方式很不方便,现在我要在线上安装上SVN的服务器,直接使用svn部署网站.因为搜盘子的服务器是ubuntu,因此下面的步骤是基于ubuntu的. 安装 ...

  7. Linux : Vim 使用与配置 (附 GitHub 自动化配置脚本)

    由于经常使用 vim 编辑配置文件,有时候也会进行使用vim 编写一些脚本和c/c++ 程序,所以配置一个常用的 vim 是很是必要的.这篇博文主要是记录vim使用和配置相关的一些知识点. 关于vim ...

  8. linux(ubuntu) 开发环境配置

    1,首先安装jdk,这是必然的. 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260 ...

  9. (4)Linux(ubuntu)下配置Opencv3.1.0开发环境的详细步骤

    Ubuntu下配置opencv3.1.0开发环境 1.最近工作上用到在Ubuntu下基于QT和opencv库开发应用软件(计算机视觉处理方面),特把opencv的配置过程详细记录,以供分享 2.步骤说 ...

随机推荐

  1. Git的安装配置(win环境)

    安装: 首先安装win版本的git msysgit:https://git-for-windows.github.io 注:安装时要勾选生成桌面快捷方式. 默认安装完后依次执行: $ git conf ...

  2. django中admin

    我们在models中建立了表结构,想要在admin中表示: from django.contrib import admin from . import models for table in mod ...

  3. ccf-20160903--炉石传说

    本题思路如下图: 题目和代码如下: 问题描述 试题编号: 201609-3 试题名称: 炉石传说 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 <炉石传说:魔兽英雄传& ...

  4. 拓普微智能TFT液晶显示模块

    关键词: 串口屏, 液晶屏, TFT,人机界面 概述: 智能模块(Smart LCD)是专为工业显示应用而设计的TFT液晶显示模块. 模块自带主控IC.Flash存储器.实时嵌入式操作系统,客户主机可 ...

  5. redis面试必问

    1.项目中缓存是如何使用的?为什么要用缓存?缓存使用不当会造成什么后果? 面试题剖析 为什么要用缓存? 用缓存,主要有两个用途:高性能.高并发. 高性能 假设这么个场景,你有个操作,一个请求过来,吭哧 ...

  6. Codeforces gym 101343 A. On The Way to Lucky Plaza【概率+逆元+精度问题】

     2017 JUST Programming Contest 2.0 题目链接:http://codeforces.com/gym/101343/problem/A A. On The Way to ...

  7. 「PKUSC2018」神仙的游戏

    题目链接 比如说上面\(|S|\)为12的字符串,我们欲求出\(f(9)\)的值,那么上面相同颜色的字符必须两两能够匹配.也就是说,同种颜色的字符集里不能同时出现0和1.如果只考虑同种颜色集里相邻的两 ...

  8. hashCode相关性能优化

    学习下hashMap中用到的关于hashCode性能优化技巧.作为笔记.为之后并发深入作基础. 1.关于提高性能的hash算法 在被模的位数为2的n次方时,用位与取代效率低下的模运算.位与效率相比模运 ...

  9. 左侧多级菜单,高亮显示js

    左侧多级菜单,如果本页面是当前栏目,则左侧菜单高亮显示 <ul class="nav navbar-stacked" id="navs"> {ded ...

  10. ESP-手机--双向通信模式

    1 AP 接受手机 2 STA(密码固定)连接路由器,AP接受手机 3 STA(密码灵活)连接路由器,AP接受手机 1 AP 接受手机 #include <ESP8266WiFi.h>   ...