使用配置文件定制bash
放入配置文件中的常见命令如下:
# 定义ls命令使用的颜色
LS_COLORS='no=00:di=01;46:ln=00;36:pi=40;33:so=00;35:bd=40;33;01'
export LS_COLORS
# 主提示符
PS1='Hello $USER'; export PS1
# 正常路径之外的个人应用程序安装目录
PATH=$PATH:/opt/MySpecialApplication/bin; export PATH 9 # 常用命令的便捷方式
function lc () {/bin/ls -C $* ; }
当用户登录shell时,会执行下列文件:
注意,如果你是通过图形化登录管理器登入的话,是不会执行/etc/profile、 HOME/.bash_profile这3个文件的。这是因为图形化窗口管理器 并不会启动shell。当你打开终端窗口时才会创建shell,但这个shell也不是登录shell。
如果.bash_profile或.bash_login文件存在,则不会去读取.profile文件。
/etc/profile, $HOME/.profile, $HOME/.bash_login, $HOME/.bash_profile /
交互式shell(如X11终端会话)或ssh执行单条命令(如ssh 192.168.1.1 ls /tmp)时,
会读取并执行以下文件:
/etc/bash.bashrc $HOME/.bashrc
如果运行如下脚本:
$> cat myscript.sh
#!/bin/bash
echo "Running"
```
不会执行任何配置文件,除非定义了环境变量BASH_ENV:
```bash
$> export BASH_ENV=~/.bashrc
$> ./myscript.sh
使用ssh运行下列命令时:会启动一个bash shell,读取并执行/etc/bash.bashrc和$HOME/.bashrc,但不包括/etc/profile或.profile。
ssh 192.168.1.100 ls /tmp
如果调用ssh登录会话:
ssh 192.168.1.100
这会创建一个新的登录bash shell,该shell会读取并执行以下文件:
/etc/profile
/etc/bash.bashrc
$HOME/.profile or .bashrc_profile
危险:像传统的Bourne shell、ash、dash以及ksh这类shell,也会读取配置文件。 但是这些shell并不支持线性数组(列表)和关联数组。因此要避免在/etc/profile或 $HOME/.profile中使用这类不支持的特性。
可以使用这些文件定义所有用户所需要的非导出项(如别名)。例如:
alias l "ls -l"
/etc/bash.bashrc /etc/bashrc
当用户登出会话时,会执行下列文件:
$HOME/.bash_logout 5
例如,远程登录的用户需要在登出的时候清屏:
$> cat ~/.bash_logout # 远程登出之后清屏 Clear
比较与测试
用于比较和测试的各种方法:
if条件
if condition;
then
commands;
fi
else if和else
if condition;
then
commands;
else if condition; then
commands;
else
commands;
fi
面向列表的for循环
for var in list;
do
commands; #使用变量$var
done
list可以是一个字符串,也可以是一个值序列。
我们可以使用echo命令生成各种值序列:
echo {1..50}; #生成一个从1~50的数字序列
echo {a..z} {A..Z}; #生成大小写字母序列
下面的代码中,变量i在每次迭代的过程里都会保存一个范围在a到z之间的字符: for i in {a..z}; do actions; done;
迭代指定范围的数字
for((i=0;i<10;i++))
{
commands; #使用变量$i
}
循环到条件满足为止
当条件为真时,while循环继续执行;当条件不为真时,until循环继续执行。
while condition
do
commands;
done
用true作为循环条件能够产生无限循环。
until循环
在Bash中还可以使用一个特殊的循环until。它会一直循环,直到给定的条件为真。例如:
x=0;
until[$x-eq9]; #条件是[$x-eq9] do
let x++; echo $x;
done
将一个命令的输出发送给另一个命令
(1)先从组合两个命令开始:
$ ls | cat -n > out.txt
ls(列出当前目录内容)的输出被传给cat -n,后者为通过stdin所接收到的输入内容 加上行号,然后将输出重定向到文件out.txt。
(2)将命令序列的输出赋给变量:
cmd_output=$(COMMANDS)
这种方法叫作子shell法。例如:
cmd_output=$(ls | cat -n)
echo $cmd_output
另一种方法叫作反引用(有些人也称它为反标记),也可以用于存储命令输出:
cmd_output=`COMMANDS`
例如:
cmd_output=`ls | cat -n`
echo $cmd_output
在不按下回车键的情况下读入n个字符
(1) 下面的语句从输入中读取n个字符并存入变量variable_name:
read -n number_of_chars variable_name
例如:
$ read -n 2 var
$ echo $var
(2) 用无回显的方式读取密码:
read -s var
(3) 使用read显示提示信息:
read -p "Enter input:" var
(4) 在给定时限内读取输入:
read -t timeout var
例如:
$ read -t 2 var #在2秒内将键入的字符串读入变量var
(5) 用特定的定界符作为输入行的结束: read -d delim_char var
例如:
$ read -d ":" var
hello: #var被设置为hello
持续运行命令直至执行成功
定义如下函数:
repeat()
{
while true
do
$@ && return
done
}
或者把它放入shell的rc文件,更便于使用:
repeat() { while true; do $@ && return; done }
加入延时
假设你要用repeat()从Internet上下载一个暂时不可用的文件,不过这个文件只需要等一会
就能下载。一种方法如下:
repeat wget -c http://www.example.com/software-0.1.tar.gz
如果采用这种形式,会产生很多发往www.example.com的流量,有可能会对服务器造成影响。 (可能也会牵连到你自己;如果服务器认为你是在向其发起攻击,就会把你的IP地址列入黑名单。)
要解决这个问题,我们可以修改函数,加入一段延时:
repeat() { while :; do $@ && return; sleep 30; done }
这样命令每30秒才会运行一次。