Shell Script

From《鸟哥的Linux私房菜——基础学习篇》Part-13
内含私货夹带

helloworld.sh

1
2
3
4
5
6
7
8
9
#!/bin/bash
# Program:
# This program shows "Hello World!" in your screen.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "Hello World! \a \n"
exit 0

Exec Shell Script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 当子进程执行完成后,子进程内的各变量或操作将结束,而不会传回给父进程
# Script在子进程中运行
# 直接执行
# helloworld.sh 必须要有可读和可执行(rx)权限
# 绝对路径
/home/xx/helloworld.sh
# 相对路径
./helloworld.sh
# 将helloworld.sh放在PATH指定的目录内
helloworld.sh
# 以bash子进程执行:
bash helloworld.sh
sh helloworld.sh
# Script在父进程中运行
# 使用 source 或者 小数点 . 来执行
source helloworld.sh
. helloworld.sh

read.sh

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
# Program:
# User inputs his first name and last name. Program shows his full name.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input your first name: " firstname # 提示用户输入
read -p "Please input your last name: " lastname # 提示用户输入
echo -e "\nYour full name is: $firstname $lastname"

create3files.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash
# Program:
# Program creates three files, which named by user's input and date command.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# 1.用户输入文件名,获取fileuser
echo -e "I will use 'touch' command to create 3 files."
read -p "Please input your filename: " fileuser
# 2.为避免用户随意按[Enter],利用变量功能分析文件名是否设置
filename=${fileuser:-"filename"} # 判断开始是否有配置文件名
# 3.date命令取日期
date1=$(date --date='2 days ago' +%Y%m%d)
date2=$(date --date='1 days ago' +%Y%m%d)
date3=$(date +%Y%d%m%d)
# 4.创建文件名
file1=${filename}${date1}
file2=${filename}${date2}
file3=${filename}${date3}
# 5.创建文件
touch "$file1"
touch "$file2"
touch "$file3"

sum.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
# Program:
# User inputs 2 integer number; program will cross these two numbers.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "You SHOULD input 2 numbers, I will cross them! \n"
read -p "first number: " firstnu
read -p "second number: " secnu
total=$(($firstnu*$secnu))
echo -e "\nThe result of $firstnu x $secnu is ==> $total"

Command test

1
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
#!/bin/bash
# Program:
# User input a filename, program will check the flowing:
# 1.exist?
# 2.file/directory?
# 3.file permissions?
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# 1.输入文件名,判断是否是字符串
echo -e "Please input a filename, i will check the filename's type and permission.\n\n"
read -p "Input a filename: " filename
test -z $filename && echo "You MUST input a filename." && exit 0
# 2.判断文件是否存在?不存在则结束脚本
test ! -e $filename && echo "The filename '$filename' DO NOT exist" && exit 0
# 3.判断文件类型和属性
test -f $filename && filetype="regulare file"
test -d $filename && filetype="directory"
test -r $filename && perm="readable"
test -w $filename && perm="$perm writable"
test -x $filename && perm="$perm executable"
# 4.echo
echo "The filename: $filename is a $filetype"
echo "And the permission are: $perm"

文件类型判断

Command Desc
test -e filename 判断filename是否存在
test -f filename 判断filename是否存在 且 是文件
test -d filename 判断filename是否存在 且 是目录
test -b filename 判断filename是否存在 且 是block device
test -c filename 判断filename是否存在 且 是character device
test -S filename 判断filename是否存在 且 是Socket
test -p filename 判断filename是否存在 且 是FIFO(pipe)
test -L filename 判断filename是否存在 且 是Link

文件权限判断

Command Desc
test -r filename 判断filename是否存在 且 具有read权限
test -w filename 判断filename是否存在 且 具有write权限
test -x filename 判断filename是否存在 且 具有execute权限
test -u filename 判断filename是否存在 且 具有set-user-id属性
test -g filename 判断filename是否存在 且 具有set-group-id属性
test -k filename 判断filename是否存在 且 具有sticky-bit属性
test -s filename 判断filename是否存在 且 不是空白文件(size>0)

文件比较

Command Desc
test file1 -nt file2 (newer than)判断file1是否比file2新
test file1 -ot file2 (older than)判断file1是否比file2旧
test file1 -ef file2 依据文件inode,判断file1和file2是否是同一个文件,可用于判断hard link

整数比较

Command Desc
test num1 -eq num2 num1 == num2 (equal)
test num1 -ne num2 num1 != num2 (not equal)
test num1 -gt num2 num1 > num2 (greater than)
test num1 -lt num2 num1 < num2 (less than)
test num1 -ge num2 num1 >= num2 (greater than or equal)
test num1 -le num2 num1 <= num2 (less than or equal)

字符串判断

Command Desc
test -z str 判断str是否为空(if str == nil {return true} return false)
test -n str 判断str是否为空(if str == nil {return false} return true)
test str1 = str2 判断str1是否等于str2
test str1 != str2 判断str1是否不等于str2

多重判断

Command Desc
test -r file -a -x file (AND) 当file同时具有r和x权限时,返回true
test -r file -o -x file (OR) 当file具有r或者x权限时,返回true
test ! -x file (NOT) 当file不具有x权限时,返回true

readPlus.sh by []

[]的用法与test基本相同
使用[]两侧必须加入空格,例[ $x == $y ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
# Program:
# This program shows the user's choice
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# 用户输入 Y y N n
read -p "Please input (Y/N): " yn
# 检查是否合法
[ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK, continue" && exit 0
[ "$yn" == "N" -o "$yn" == "n" ] && echo "OH, interrupt!" && exit 0
echo "I don't know what your choice is" && exit 0

Shell Script Default Arguments $0,$1...

1
2
3
4
5
6
7
8
# 执行脚本
/home/xx/arg.sh arg1 arg2 arg3
$0 $1 $2 $3
# 以下特殊变量可在脚本中使用
$# # 代表脚本参数个数 上例中为3
$@ # 代表 "$1" "$2" "$3" 每个参数独立在双引号内
$* # 代表 "$1 $2 $3" 每个参数之间用空格分隔

echoArg.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
# Program:
# Program shows the script name, parameters...
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "The script name is ==> $0"
echo "Total parameter number is ==> $#"
[ "$#" -lt 2 ] && echo "The number of parameter is less than 2. Stop here." && exit 0
echo "Your whole parameter is ==> '$@'"
echo "The 1st parameter ==> $1"
echo "The 2nd parameter ==> $2"
1
2
3
4
5
6
sh echoArg.sh theone haha quot
# The script name is ==> echoArg.sh
# Total parameter number is ==> 3
# Your whole parameter is ==> 'theone haha quot'
# The 1st parameter ==> theone
# The 2nd parameter ==> haha

shift.sh 变量偏移

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
# Program:
# Program shows the effect of shift function.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
shift # shift 一个
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
shift 3 # shift 三个
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
1
2
3
4
5
6
7
8
9
10
11
sh shift.sh one two three four five six
# 原始参数
# Total parameter number is ==> 6
# Your whole parameter is ==> 'one two three four five six'
# 偏移1位
# Total parameter number is ==> 5
# Your whole parameter is ==> 'two three four five six'
# 偏移3位
# Total parameter number is ==> 2
# Your whole parameter is ==> 'five six'

if.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
# Program:
# This program shows the user's choice.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input(Y/N): " yn
if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
echo "OK, continue"
exit 0
fi
if [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
echo "OH, interrupt!"
exit 0
fi
echo "I don't know what your choice is" && exit 0

ifElse.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
# Program:
# This program shows the user's choice.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input(Y/N): " yn
if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
echo "OK, continue"
elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
echo "OH, interrupt!"
else
echo "I don't know what your choice is"
fi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
# Program:
# Check $1 is equal to "hello"
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
if [ "$1" == "hello" ]; then
echo "Hello, how are you?"
elif [ "$1" == "" ]; then
echo "You MUST input parameter, ex> {$0 someword}"
else
echo "The only parameter is 'hello', ex> {$0 hell0}"
fi
1
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
#!/bin/bash
# Program:
# Using netstat and grep to detect WWW,SSH,FTP and Mail services.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "Now, i will detect your Linux server's services!"
echo -e "The www,ssh,ftp and mail will be detect!\n"
testing=$(netstat -tuln | grep ":80 ")
if [ "$testing" != "" ]; then
echo "WWW is running in your system."
fi
testing=$(netstat -tuln | grep ":22 ")
if [ "$testing" != "" ]; then
echo "SSH is running in your system."
fi
testing=$(netstat -tuln | grep ":21 ")
if [ "$testing" != "" ]; then
echo "FTP is running in your system."
fi
testing=$(netstat -tuln | grep ":25 ")
if [ "$testing" != "" ]; then
echo "Mail is running in your system."
fi
1
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
31
#!/bin/bash
# Program:
# You input your demobilization date.
# I calculate how many days before you demobilize.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "This program will try to calculate :"
echo "How many days before your demobilization date..."
read -p "Please input your demobilization date (YYYYMMDD ex>20090401): " date2
date_d=$(echo $date2 |grep '[0-9]\{8\}')
if [ "$date_d" == "" ]; then
echo "You input the wrong date format...."
exit 1
fi
declare -i date_dem=`date --date="$date2" +%s`
declare -i date_now=`date +%s`
declare -i date_total_s=$(($date_dem-$date_now))
declare -i date_d=$(($date_total_s/60/60/24))
if [ "$date_total_s" -lt "0" ]; then
echo "You had been demobilization before: " $((-1*$date_d)) " ago"
else
declare -i date_h=$(($(($date_total_s-$date_d*60*60*24))/60/60))
echo "You will demobilize after $date_d days and $date_h hours."
fi

case.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
# Program:
# Show "Hello" from $1...
# By using case...esac
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
case $1 in
"hello")
echo "Hello, how are you?"
;;
"")
echo "You MUST input parameter, ex> {$0 someword}"
;;
*) # default
echo "Usage $0 {hello}"
;;
esac
1
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
#!/bin/bash
# Program:
# Show "Hello" from $1...
# By using case...esac
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "This program will print your selection!"
# read -p "Input your choice: " choice
# case $choice in
case $1 in
"one")
echo "Your choice is ONE"
;;
"two")
echo "Your choice is TWO"
;;
"three")
echo "Your choice is THREE"
;;
*)
echo "Usage $0 {one|two|three}"
;;
esac

function.sh

1
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
#!/bin/bash
# Program:
# Use function to repeat information.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
function printit() {
echo -n "Your choice is "
}
echo "This program will print your selection!"
case $1 in
"one")
printit; echo $1 | tr 'a-z' 'A-Z'
;;
"two")
printit; echo $1 | tr 'a-z' 'A-Z'
;;
"three")
printit; echo $1 | tr 'a-z' 'A-Z'
;;
*)
echo "Usage $0 {one|two|three}"
;;
esac
1
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
#!/bin/bash
# Program:
# Use function to repeat information.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
function printit() {
echo -n "Your choice is $1"
}
echo "This program will print your selection!"
case $1 in
"one")
printit 1
;;
"two")
printit 2
;;
"three")
printit 3
;;
*)
echo "Usage $0 {one|two|three}"
;;
esac

while.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
# Program:
# Use loop to calculate "1+2+3+...+100" result.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
s=0
i=0
while [ "$i" != "100" ]
do
i=$(($i+1))
s=$(($s+$i))
done
echo "The result of '1+2+3+...+100' is ==> $s"
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
# Program:
# Repeat question until user input correct answer.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
while [ "$yn" != "yes" -a "$yn" != "YES" ]
do
read -p "Please input yes/YES to stop this program: " yn
done
echo "OK!you input the correct answer."

until.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
# Program:
# Repeat question until user input correct answer.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
until [ "$yn" == "yes" -a "$yn" == "YES" ]
do
read -p "Please input yes/YES to stop this program: " yn
done
echo "OK!you input the correct answer."

for.sh

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
# Program:
# Using for ... loop to print 3 animals
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
for animal in dog cat elephant
do
echo "There are ${animal}s..."
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
# Program:
# Use id, finger command to check system account's information.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
users=$(cut -d ':' -f1 /etc/passwd)
for username in $users
do
id $username
finger $username
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
# Program:
# Use ping command to check the network's PC state.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
network="192.168.1.1"
for sitenu in $(seq 1 100)
do
ping -c 1 w 1 ${network}.${sitenu} &> /dev/null && result=0 || result=1
if [ $result == 0 ]; then
echo "Server ${network}.${sitenu} is UP."
else
echo "Server ${network}.${sitenu} is DOWN."
fi
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
# Program:
# User input dir name, i find the permission of files.
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input a directory: " dir
if [ "$dir" == "" -o ! -d "$dir" ]; then
echo "This $dir is NOT exist in your system."
exit 1
fi
filelist=$(ls $dir)
for filename in $filelist
do
perm=""
test -r "$dir/$filename" && perm="$perm readable"
test -w "$dir/$filename" && perm="$perm writable"
test -x "$dir/$filename" && perm="$perm executable"
echo "The file $dir/$filename's permission is $perm"
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
# Program:
# Try do calculate 1+2+...+${user_input}
# History:
# 2017/01/01 beiping96 First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input a number, i will count for 1+2+...+user_input: " nu
s=0
for (( i=1; i<=$nu; i=i+1 ))
do
s=$(($s+$i))
done
echo "The result of '1+2+...+$nu' is ==> $s"

SVN_post_commit.sh

1
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
#!/bin/bash
# Program:
# Add Jira comment when SVN commit
# history:
# 2017/02/28 beiping96 First release
# 2017/03/01 beiping96 Format comment
REPOS="$1"
REV="$2"
LOG=`svnlook log -r $REV $REPOS`
LOG_INFO="User:"
LOG_INFO=${LOG_INFO}`svnlook author -r $REV $REPOS`
LOG_INFO=${LOG_INFO}" \\\\\\\\Comment:${LOG} \\\\\\\\SVN_ID:${REV} \\\\\\\\ Change: "
LOG_INFO=${LOG_INFO}`echo $(svnlook changed -r $REV $REPOS)`
LOG_INFO=`echo ${LOG_INFO} | sed 's/[[:space:]][[:space:]]*[ADU_][U[:space:]]/ \\\\\\\\\\\\\\\\ /g'`
LOG_INFO=`echo ${LOG_INFO}`
# Parse Jira issue id
function parse_jira_ids() {
for ID in "$(echo $LOG | grep -Po '[A-Z]*-[0-9]*')"
do
echo $ID
done
}
JIRA_IDS=$(parse_jira_ids)
for JIRA_ID in $JIRA_IDS
do
curl -D- -u xingrui:112233 -X POST --data "{\"body\":\"${LOG_INFO}\"}" -H "Content-Type: application/json" http://xx.com:8088/rest/api/2/issue/"$JIRA_ID"/comment
done

Shell Script DEBUG

Command Desc
sh -n xx.sh 不运行,仅检查语法问题
sh -v xx.sh 运行前,先将xx.sh的内容打印到屏幕
sh -x xx.sh 将xx.sh的运行过程全部列出来(常用)