常用 shell 脚本样例
# 参数
- $0 : 脚本名称
- $1 : 第一个参数
- $2 : 第一个参数
- $3 : 依次类推 $5 $6 …
- $# : 参数的个数,不包括命令本身,上例中$#为5.
- $@ : 参数本身的列表,也不包括命令本身
- $* : 参数本身的列表,也不包括命令本身
示例
#!/bin/bash
echo '
- $0 : 脚本名称
- $1 : 第一个参数
- $2 : 第一个参数
- $3 : 依次类推 $5 $6 …
- $# : 参数的个数,不包括命令本身,上例中\$#为5.
- $@ : 参数本身的列表,也不包括命令本身
- $* : 参数本身的列表,也不包括命令本身,与 $@ 的区别是:$@ 是一个数组,$* 是一个字符串
'
echo '$0 - '$0
echo '$1 - '$1
echo '$2 - '$2
echo '$#' - $#
echo '$@ loop start'
for arg in "$@"
do
echo $arg
done
echo '$@ loop end'
echo '$* loop start'
for arg in "$*"
do
echo $arg
done
echo '$* loop end'
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
输出
$ bash a.sh a=1 b c --out /path/to
$0 - a.sh
$1 - a=1
$2 - b
$# - 5
$@ loop start
a=1
b
c
--out
/path/to
$@ loop end
$* loop start
a=1 b c --out /path/to
$* loop end
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# shell 脚本样例
处理命令行参数
while [ "$1" != "" ]; do case $1 in -s ) shift SERVER=$1 ;; -d ) shift DATE=$1 ;; --paramter|p ) shift PARAMETER=$1;; -h|help ) usage # function call exit ;; * ) usage # All other parameters exit 1 esac shift done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15命令行菜单
#!/bin/bash # Bash Menu Script Example PS3='Please enter your choice: ' options=("Option 1" "Option 2" "Option 3" "Quit") select opt in "${options[@]}" do case $opt in "Option 1") echo "you chose choice 1" ;; "Option 2") echo "you chose choice 2" ;; "Option 3") echo "you chose choice $REPLY which is $opt" ;; "Quit") break ;; *) echo "invalid option $REPLY";; esac done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23获取当前运行脚本绝对路径
FILE="$0" while [[ -h ${FILE} ]]; do FILE="`readlink "${FILE}"`" done pushd "`dirname "${FILE}"`" > /dev/null DIR=`pwd -P` popd > /dev/null
1
2
3
4
5
6
7颜色定义
RCol='\e[0m' # Text Reset # Regular Bold Underline High Intensity BoldHigh Intens Background High Intensity Backgrounds Bla='\e[0;30m'; BBla='\e[1;30m'; UBla='\e[4;30m'; IBla='\e[0;90m'; BIBla='\e[1;90m'; On_Bla='\e[40m'; On_IBla='\e[0;100m'; Red='\e[0;31m'; BRed='\e[1;31m'; URed='\e[4;31m'; IRed='\e[0;91m'; BIRed='\e[1;91m'; On_Red='\e[41m'; On_IRed='\e[0;101m'; Gre='\e[0;32m'; BGre='\e[1;32m'; UGre='\e[4;32m'; IGre='\e[0;92m'; BIGre='\e[1;92m'; On_Gre='\e[42m'; On_IGre='\e[0;102m'; Yel='\e[0;33m'; BYel='\e[1;33m'; UYel='\e[4;33m'; IYel='\e[0;93m'; BIYel='\e[1;93m'; On_Yel='\e[43m'; On_IYel='\e[0;103m'; Blu='\e[0;34m'; BBlu='\e[1;34m'; UBlu='\e[4;34m'; IBlu='\e[0;94m'; BIBlu='\e[1;94m'; On_Blu='\e[44m'; On_IBlu='\e[0;104m'; Pur='\e[0;35m'; BPur='\e[1;35m'; UPur='\e[4;35m'; IPur='\e[0;95m'; BIPur='\e[1;95m'; On_Pur='\e[45m'; On_IPur='\e[0;105m'; Cya='\e[0;36m'; BCya='\e[1;36m'; UCya='\e[4;36m'; ICya='\e[0;96m'; BICya='\e[1;96m'; On_Cya='\e[46m'; On_ICya='\e[0;106m'; Whi='\e[0;37m'; BWhi='\e[1;37m'; UWhi='\e[4;37m'; IWhi='\e[0;97m'; BIWhi='\e[1;97m'; On_Whi='\e[47m'; On_IWhi='\e[0;107m'; echo -e "${Blu}blue ${Red}red ${RCol}etc...."
1
2
3
4
5
6
7
8
9
10
11
12
13远程服务器运行一个本地脚本
#无参数 ssh user@server 'bash -s' < local.script.sh #有参数 ssh user@server ARG1="arg1" ARG2="arg2" 'bash -s' < local_script.sh
1
2
3
4
5定时按日期删除历史文件
find /path/to/data/ -type f -name "*.zip" -mtime +7 # 可以加入到 crontab 自动执行:0 0 * * * find /path/to/data/ -type f -name "*.zip" -mtime +7 -exec rm -rf {} \;
1
2
# 写出健壮性更好的脚本
使用
-e
参数,如:set -e
或是#!/bin/sh -e
,这样设置会让你的脚本出错就会停止运行,这样一来可以防止你的脚本在出错的情况下还在拼拿地干活停不下来。使用
-u
参数,如:set -eu
,这意味着,如果你代码中有变量没有定义,就会退出。对一些变理,你可以使用默认值。如:
${FOO:-'default'}
处理你代码的退出码。这样方便你的脚本跟别的命令行或脚本集成。
尽量不要使用
;
来执行多个命令,而是使用&&
,这样会在出错的时候停止运行后续的命令。对于一些字符串变量,使用引号括起,避免其中有空格或是别的什么诡异字符。
如果你的脚有参数,你需要检查脚本运行是否带了你想要的参数,或是,你的脚本可以在没有参数的情况下安全的运行。
为你的脚本设置
-h
和--help
来显示帮助信息。千万不要把这两个参数用做为的功能。使用
$()
而不是 “ 来获得命令行的输出,主要原因是易读。小心不同的平台,尤其是 MacOS 和 Linux 的跨平台。
对于
rm -rf
这样的高危操作,需要检查后面的变量名是否为空,比如:rm -rf $MYDIDR/*
如果$MYDIR
为空,结果是灾难性的。考虑使用
find/while
而不是for/find
。如:for F in $(find . -type f) ; do echo $F; done 写成 find . -type f | while read F ; do echo $F ; done
不但可以容忍* 空格,而且还更快。防御式编程,在正式执行命令前,把相关的东西都检查好,比如,文件目录有没有存在。
参考: