第二章
1. shell环境
shell在shell会话中保存着大量信息。这些信息被称为shell的环境。程序获取环境中的数据(环境变量)来了解本机的配置。虽然大多数程序用配置文件来存储程序设置,一些程序会根据环境变量来调整他们的行为。
printenv - 打印部分或所有的环境变量
set - 设置shell选项
export - 导出环境变量,让随后执行的程序知道
alias - 创建命令别名
什么存储在环境变量中?
shell在环境中存储了两种基本类型的数据,虽然bash几乎无法分辨这些数据的类型。它们是环境变量和shell变量。shell变量是bash存放的少量数据。剩下的都是环境变量。除了变量,shell也存储了一些可编程的数据,即别名和shell函数。
检查环境变量
我们可以用bash的内建命令,或者是printenv程序来查看环境变量。set命令可以显示shell或环境变量,而printenv只是显示环境变量。
printenv命令也能够列出特定变量的数值:
printenv USER #me
当使用没有带选项和参数的set命令时,shell变量,和定义的shell函数都会被显示。不同于printenv命令,set命令的输出很友好地按照首字母顺序排列。
也可以通过echo命令来查看一个变量的内容:
echo $HOME #/home/me
别名无法通过set或printenv来查看,用不带参数的alias来查看别名。
一些有趣的环境变量
环境变量
变量 | 含义 |
---|---|
DISPLAY | 如果你正在运行图形界面环境,那么这个变量就是你显示器名字。通常它是:o |
EDITOR | 文本编辑器的名字 |
SHELL | shell程序的名字 |
HOME | 用户家目录 |
LANG | 定义了字符集以及语言编码方式 |
OLD_PWD | 先前的工作目录 |
PAGER | 页输出程序的名字,这经常设置为/usr/bin/less |
PATH | 由冒号分开的目录列表,当你输出可执行程序名后,会搜索这个目录列表 |
PS1 | Prompt String1.这个定义了你的shell提示符的内容 |
PWD | 当前工作目录 |
TERM | 终端类型名。类Unix的系统支持许多终端协议,这个变量设置你的终端仿真器所用的协议 |
TZ | 指定你所在的时区。 |
USER | 你的用户名 |
如何建立shell环境
当我们登录系统后,bash程序启动,并且会读取一系列称为启动文件的配置脚本,这些文件定义了默认的可供所有用户共享的shell环境。然后读取更多位于我们自己家目录中的启动文件,这些启动文件定义了用户个人的shell环境。确切的启动顺序依赖于要运行的shell会话类型。
有两种shell会话类型:一个是登录shell会话,另一个是非登录shell会话。
登录shell会话会在其中提醒用户输入用户名和密码,例如,我们启动一个虚拟控制台会话。非登录shell会话通常当我们在GUI下启动终端会话时出现。
登录shell会读取一个或多个启动文件:
登录shell会话的启动文件
文件 | 内容 |
---|---|
/etc/profile | 应用于所有用户的全局配置脚本 |
~/.bash_profile | 用户个人的启动文件。可以用来扩展或重写全局配置脚本中的设置 |
~/.bash_login | 如果文件~/.bash_profile没有找到,bash会尝试读取这个脚本 |
~/.profile | 如果文件~/.bash_profile或文件~/.bash_login都没有找到,bash会尝试读取这个文件。 |
非登录shell会话的启动文件
文件 | 含义 |
---|---|
/etc/bash.bashrc | 应用于所有用户的全局配置文件 |
~/.bashrc | 用户个人的启动文件。可以用来扩展或重写全局配置脚本中的设置 |
除了读取以上启动文件之外,非登录shell会话也会继承它们父进程的环境设置,通常是一个登录shell。
文件~/.bashrc可能是重要启动文件,因为它几乎总是被读取。
经常在/etc/profile启动文件中设置PATH变量:
PATH=$PATH:$HOME/bin
添加目录$HOME/bin到目录列表的末尾
使用这种技巧,我们可以把文本附加到一个变量值得末尾。
如果我们想要在自己的家目录下创建一个目录来存储我们自己的私人程序时,shell已经给我们准备好了,我们所要做的事就是把创建的目录叫做bin。
export PATH
这个export命令告诉shell让这个shell的子进程可以使用PATH变量的内容。
补充知识
登录shell是可以用户登录使用的,比如/bin/bash ,/bin/sh ,/bin/csh…一般 Linux默认的用户shell都是bash,也就是你可以登录进去写命令。
非登录shell:经典的/bin/nologin就是一个非登录shell,也就是说如果一个用户默认的是它,这个用户即使登录进linux也无法使用linux。
shell是用户和计算机交流的媒介,登录shell保证用户和计算机交流,非登录shell无法让计算机和用户交流。关于用户的默认登录shell是在/etc/passwd文件中记录的。
非登录shell有他特定的用途,比如一个用linux搭建的ftp服务器,并且创建了多个用户,那么就可以将这些用户默认shell改成nologin,这样一来,这些用户虽然是linux上的用户却无法登录进linux主机,只能进入ftp服务器,这样也保证了安全!
修改shell环境
按照通常的规则,添加目录到你的PATH变量或者是定义额外的环境变量,要把这些更改放置到.bash_profile文件中(或者其他代替文件中)。对于其他的更改,要放到.bashrc文件中。除非你是系统管理员,需要为系统中的所有用户修改默认设置,那么则限定你只能对自己家目录下的文件进行修改。
文本编辑器
为了编辑shell的启动文件以及系统中大多数其他配置文件,我们使用一个叫做文本编辑器的程序。
文本编辑器分为两种基本类型:图形化和基于文本的编辑器。
使用文本编辑器
所有的文本编辑器都可以在命令行中输入编辑器的名字,加上你所想要的文件来唤醒。如果你输入的文件名不存在,编辑器则会假定你想要创建一个新文件。
重新读取某个修改过的文件:
source file_changed
2. vi简介
如果你在vi中迷失了,试着按下ESC键两次回到普通模式。
如果vim编辑器中有“运行于Vi兼容模式”,这意味着vim将以近似于vi的普通的模式运行,而不是以vim的高级的模式运行。如果要使用vim的高级模式,可以通过如下方法:
在/.bashrc文件中添加alias vi=‘vim’
或者,使用以下命令在你的vim配置文件中添加一行:
echo “set nocp” >> ~/.vimrc
vi启动后会直接进入命令模式,这种模式下,几乎每个按键都是一个命令。每行开头的波浪号(~)表示那一行没有文本。
移动光标
光标移动按键
按键 | 移动光标 |
---|---|
l or 右箭头 | 向右移动一个字符 |
h or 左箭头 | 向左移动一个字符 |
j or 下箭头 | 向下移动一行 |
k or 上箭头 | 向上移动一行 |
0(零按键) | 移动到当前行的行首 |
^ | 移动到当前行的第一个非空字符 |
$ | 移动到当前行的末尾 |
w | 移动到下一个单词或标点符号的开头 |
W | 移动到下一个单词的开头,忽略标点符号 |
b | 移动到上一个单词或标点符号的开头 |
B | 移动到上一个单词的开头,忽略标点符号 |
ctrl-f or page down | 向下翻一页 |
ctrl-b or page up | 向上翻一页 |
numberG | 移动到第number行 |
G | 移动到文件末尾 |
基本编辑
如果我们按下“u”按键,当在命令模式下,将会撤销你所做的最后一个修改。
对于追加文本的命令,如果我们把光标移动到行尾,输入“a“,光标就会越过行尾,同时进入插入模式。输入”A“光标将移动到行尾,同时vi进入输入模式。
文本行打开按键
命令 | 打开行 |
---|---|
o | 当前行的下方打开一行 |
O | 当前行的上方打开一行 |
删除文本
命令 | 删除的文本 |
---|---|
x | 当前字符 |
3x | 当前字符以及后面的两个字符 |
dd | 当前行 |
5dd | 当前行以及随后的四行文本 |
dW | 从光标位置开始到下一个单词的开头 |
d$ | 从光标位置开始到当前行的行尾 |
d0 | 从光标位置开始到当前行的行首 |
d^ | 从光标位置开始到文本行的第一个非空字符 |
dG | 从当前行到文件的末尾 |
d20G | 从当前行到文件的第20行 |
剪切,复制和粘贴文本
这个d命令不仅删除文本,它还剪切文本。每次我们使用d命令,删除的部分被复制到一个粘贴换冲区中。
复制命令
命令 | 复制的内容 |
---|---|
yy | 当前行 |
5yy | 当前行以及随后的四行文本 |
yW | 从当前光标位置到下一个单词的开头 |
y$ | 从当前光标位置到当前行的末尾 |
y0 | 从当前光标位置到行首 |
y^ | 从当前光标位置到文本行的第一个非空字符 |
yG | 从当前行到文件末尾 |
y20G | 从当前行到文件的第20行 |
输入小写的p把复制的一行粘贴到当前行的下面,输入大写的P命令把所复制的文本粘贴到当前行之上。
连接行
通常,用户不可能通过删除”行尾结束符“来连接当前行和它下面的一行。由于这个原因,vi提供了一个特定的命令,大写的J用来连接行与行。
查找与替换
f命令能搜索一特定行,并将光标移动到下一个匹配的字符上。例如,命令fa会把光标定位到同一行中下一个出现的a字符上。在进行了一次行内搜索后,输入分号能重复这次搜索。
移动光标到下一个出现的单词或短语上,使用/命令。这个命令和我们之前在less程序中学到的一样。当你输入/命令后,一个/字符就会出现在屏幕底部。接下来,输入要查找的单词或短语,按下回车,光标就会移动到下一个包含所查找字符串的位置。通过n命令来重复先前的查找。
全局查找和替换
:%s/Line/line/g
条目 | 含义 |
---|---|
: | 冒号字符运行一个ex命令 |
% | 指定要操作的行数。%是一个快捷方式,表示从第一行到最后一行。另外,操作范围也可以用1,5来代替。或者用1,$代替,意思是"从第一行到文件的最后一样" 。如果省略了文本行的范围,那么操作只对当前行生效 |
s | 指定操作。在这种情况下,是替换(查找与替代) |
/Line/line | 查找类型与替代为本 |
g | 这是全局的意思。意味着对文本行中所有匹配字符串执行查找和替换操作。如果省略g,则只替换每个文本行中第一个匹配的字符串 |
通过在命令末尾添加一个c字符,来实现让用户确认的替换命令。
编辑多个文件
vi file1 file2…
文件之间切换
从这个文件切换到下一个文件:
:n
回到先前的文件使用:
:N
查看正在编辑的文件列表:
:buffers
要切换到另一个缓冲区(文件):
:buffers 文件编号
打开另一个文件并编辑
vi file1
这时要打开第二个文件,输入:
:e file2
当文件由:e命令加载,你将无法用:n或:N命令来切换文件。这时要使用:buffer命令加载缓冲区号码,来切换文件。
插入整个文件到另一个文件
vi file1
:r命令把指定的文件插入到光标位置的之前。
:r foo.txt
3. 自定制shell提示符
我们默认的提示符看起来像这样:
[me@linuxbox ~]$
注意它包含我们的用户名,主机名和当前工作目录。提示符是由一个环境变量定义的,叫做PS1(是"prompt string one"的简写)。我们可以通过echo命令来查看PS1内容。
[me@linuxbox ~]$echo $PS1
[\u@\h \W]$
从输出结果中,我们看到那个PS1环境变量包含一些的字符,这些可以看作是由反斜杠转义的特殊字符。
shell提示符中用到的转义字符
序列 | 含义 |
---|---|
\a | 以ASCII格式编码的铃声,当遇到这个转义序列时,计算机会发出嗡嗡的响声 |
\d | 以日,月,天格式来表示当前日期 |
\h | 本地的主机名,但不带末尾的域名 |
\H | 完整的主机名 |
\j | 运行在当前shell会话中的工作数 |
\l | 当前终端设备名 |
\n | 一个换行符 |
\r | 一个回车符 |
\s | shell程序名 |
\t | 以24小时制,hours:minutes:seconds的格式表示当前时间 |
\T | 以12小时制表示当前时间 |
@ | 以12小时制,AM/PM格式来表示当前时间 |
\A | 以24小时制,hours:minutes格式表示当前时间 |
\u | 当前用户名 |
\v | shell程序的版本号 |
\V | Version and release numbers of the shell |
\w | 当前工作目录名 |
\W | 当前工作目录名的最后部分 |
! | 当前命令的历史号 |
# | 当前shell会话中的命令数 |
$ | 这会显示一个"$“字符,除非你拥有超级用户权限。在这种情况下,它会显示一个”#"字符 |
[ | 标志着一系列一个或多个非打印字符的开始。这被用来嵌入非打印的控制字符,这些字符以某种方式来操作终端仿真器,比方说移动光标或者是更改文本颜色 |
] | 标志着非打印字符序列结束 |
添加颜色
字符颜色是由发送到终端仿真器的一个嵌入到了要显示的字符流中的ANSI转义编码来控制的。这个控制编码不会“打印”到屏幕上,而是被终端解释为一个指令。正如我们在上表看到的字符序列,这个[和]序列被用来封装这些非打印字符。一个ANSI转义编码以一个八进制033(这个编码是由退出键产生的)开头,其后跟着一个可选的字符属性,在之后是一个指令。例如,把文本颜色设为正常(attribute=0),黑色文本的编码如下:
\033[0;30m
这里是一个可用的文本颜色列表。注意这些颜色被分成两组,由应用程序粗体字符属性(1)分化开来,这个属性可以描绘出“浅”色文本。
用转义序列来设置文本颜色
序列 | 文本 | 序列 | 文本 |
---|---|---|---|
\033[0;30m | 黑色 | \033[1;30m | 深灰色 |
\033[0;31m | 红色 | \033[1;31m | 浅红色 |
\033[0;32m | 绿色 | \033[1;32m | 浅绿色 |
\033[0;33m | 棕色 | \033[1;33m | 黄色 |
\033[0;34m | 蓝色 | \033[1;34m | 浅蓝色 |
\033[0;35m | 粉红 | \033[1;35m | 浅粉色 |
\033[0;36m | 青色 | \033[1;36m | 浅青色 |
\033[0;37m | 浅灰色 | \033[1;37m | 白色 |
下面最制作一个红色提示符,我们将在开头加入转义编码:
<me@linuxbox ~>$ PS1=’[\033[0;31m]<\u@\h \W>$’
这个在提示符之后输入的文本也是红色的,为了修改这个问题,我们将添加另一个转义编码到这个提示符的末尾来告诉终端仿真器恢复到原来的颜色:
<me@linuxbox ~>$ PS1=’[\033[0;31m]<\u@\h \W>$[\033[0m]’
也有可能要设置文本的背景颜色,使用下面列出的转义编码。这个背景颜色不支持黑体属性。
用转义序列来设置背景颜色
序列 | 颜色 | 序列 | 颜色 |
---|---|---|---|
\033[0;40m | 蓝色 | \033[1;44m | 黑色 |
\033[0;41m | 红色 | \033[1;45m | 紫色 |
\033[0;42m | 绿色 | \033[1;46m | 青色 |
\033[0;43m | 棕色 | \033[1;47m | 浅灰色 |
下面创建一个带有红色背景的提示符,只是对第一个转义编码做个简单的修改。
<me@linuxbox ~>$ PS1=’[\033[0;41m]<\u@\h \W>$[\033[0m] ’
注意:除了正常的(0)和黑体(1)字符属性之外,文本也可以具有下划线(4),闪烁(5),和反向(7)属性。
移动光标
转义编码也可以用来定位光标,这些编码被普遍地用来,每次当提示符出现的时候,会在屏幕的不同位置上比如说上面一个角落,显示一个时钟或者其它一些信息。这里是一系列用来定位光标的转义编码:
光标移动转义序列
转义编码 | 行动 |
---|---|
\033[1;cH | 把光标移动到第1行,第c列 |
\033[nA | 把光标向上移动n行 |
\033[nB | 把光标向下移动n行 |
\033[nC | 把光标向前移动n个字符 |
\033[nD | 把光标向后移动n个字符 |
\033[2J | 清空屏幕,把光标移到左上角(第零行,第零列) |
\033[K | 清空从光标位置到当前行末的内容 |
\033[s | 存储当前光标位置 |
\033[u | 唤醒之前存储的光标位置 |
保存提示符
通过把提示符添加到我们的.bashrc文件,我们使这个提示符永久存在。为了达到这个目的,把下面这两行添加到.bashrc文件中:
PS1='\[\033[s\033[0;0H\033[0;41m\033[K\033[1;33m\t\033[0m\033[u\]<\u@\h \W>\$ '
export PS1