学习 Shell Scripts
1、第一支 script 的撰写与执行
现在我们假设你写的这个程序文件名是 /home/dmtsai/shell.sh,那么如何执行这个文件呢?
- 直接指令下达:shell.sh 文件必须要具备可读与可执行(rx)的权限,然后:
- 绝对路径:使用 /home/dmtsai/shell.sh 来下达指令;
- 相对路径:假设工作目录在 /home/dmtsai,则使用 ./shell.sh 来执行;
- 变量 “PATH” 的功能:将 shell.sh 放在 PATH 指定的目录内,例如:~/bin/
- 以 bash 程序来执行:通过 “bash shell.sh” 或 “sh shell.sh” 来执行
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
export PATH
echo -e "Hello World! \a \n"
exit 0
-
第一行 #!/bin/bash 在宣告这个 script 使用的 shell 名称: 因为我们使用的是 bash,所以,必须要以 “#!/bin/bash” 来宣告这个文件内的语法使用 bash 的语法。那么当这个程序被执行时,他就能加载 bash 的相关环境配置文件(一般来说就是 non-login shell 的 ~/.bashrc)并且执行 bash 来使我们底下的指令能够执行。 -
程序内容说明 建议添加说明:1、内容与功能;2、版本信息;3、作者与联系方式;4、文件日期;5、历史记录。 -
主要环境的宣告 PATH -
主要程序部分 -
执行结果告知(定义回传值)
[root@MiWiFi-R4A-srv ~]
Hello World!
2、简单的 shell script 练习
2.1、简单范例
2.1.1、对谈式脚本:变量内容由用户决定
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
read -p "Please input your first name:" firstname
read -p "Please input your last name:" lastname
echo -e "\n Your full name is: ${firstname} ${lastname}"
2.1.2、随日期变化:利用 date 进行文件的建立
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
echo -e "I will use 'touch' command to create 3 files."
read -p "Please input your filename:" fileuser
filename=${fileuser:-"filename"}
date1=$(date --date='2 days ago' +%Y%m%d)
date2=$(date --date='1 days ago' +%Y%m%d)
date3=$(date +%Y%m%d)
file1=$(filename)$(date1)
file2=$(filename)$(date2)
file3=$(filename)$(date3)
touch "$(file1)"
touch "$(file2)"
touch "$(file3)"
2.1.3、数值运算:简单的加减乘除
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
echo -e "You Should input 2 numbers, I will multiplying them! \n"
read -p "first number: " firstnu
read -p "second number: " secondnu
total=$((${first}*${secondnu}))
echo -e "\n The result of ${firstnu} * ${secondnu} is ==> ${total}"
2.1.4、通过 bc 计算 pi
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
echo -e "This program will calculate pi value. \n"
echo -e "You should input a float number to calculate pi value. \n"
read -p "The scale number (10~10000) ?" checking
num=${checking:-"10"}
echo -e "Starting calculate pi value. Be patien."
time echo "scale=${num}; 4*a(1)" | bc -lp
2.2、script 的执行方式差异(source,sh script,./script)
2.2.1、利用直接执行的方式来执行 script
不论是直接指令下达,或者是利用 bash 来下达指令,该 script 都会使用一个新的 bash 环境来执行脚本内的指令!重点在于:当子程序完成后,在子程序内的各项变量或动作将会结束而不会传到父程序中!
如果使用 Windows 编辑的脚本,请使用:
sed -i ‘s/\r//’ 脚本名
[root@MiWiFi-R4A-srv bash]
<== 确认了,这两个变量并不存在!
[root@MiWiFi-R4A-srv bash]
Please input your first name:VBird
Please input your last name:Tsai
Your full name is: VBird Tsai
[root@MiWiFi-R4A-srv bash]
<== 事实上,这两个变量在父程序中的 bash 中还是不存在
[root@MiWiFi-R4A-srv bash]
[root@MiWiFi-R4A-srv bash]
Please input your first name:VBird
Please input your last name:Tsai
Your full name is: VBird Tsai
[root@MiWiFi-R4A-srv bash]
<== 同样这两个变量在父程序中的 bash 中还是不存在
2.2.2、利用 source 来执行脚本:在父程序中执行
[root@MiWiFi-R4A-srv bash]
Please input your first name:VBird
Please input your last name:Tsai
Your full name is: VBird Tsai
[root@MiWiFi-R4A-srv bash]
VBird Tsai
3、善用判断式
3.1、利用 test 指令的测试功能
[root@MiWiFi-R4A-srv bash]
执行结果并不会显示任何信息,但最后我们可以通过 $? 或 && 及 || 来展示整个结果!
[root@MiWiFi-R4A-srv bash]
Not Exist
[root@MiWiFi-R4A-srv bash]
exist
测试的标志 | 代表意义 |
---|
1.关于某个文件名的 “文件类型” 判断 | | -e | 该 “文件名” 是否存在? | -f | 该 “文件名” 是否存在且为文件(file)? | -d | 该 “文件名” 是否存在且为目录(directory)? | -b | 该 “文件名” 是否存在且为一个 block device 设备? | -c | 该 “文件名” 是否存在且为 character device 设备? | -S | 该 “文件名” 是否存在且为 Socket 文件? | -p | 该 “文件名” 是否存在且为一个 FIFO(pipe)文件? | -L | 该 “文件名” 是否存在且为一个连结文件? | 2.关于文件的权限侦测 | | -r | 侦测该文件名是否存在且具有 “可读” 的权限? | -w | 侦测该文件名是否存在且具有 “可写” 的权限? | -x | 侦测该文件名是否存在且具有 “可执行” 的权限? | -u | 侦测该文件名是否存在且具有 “SUID” 的权限? | -g | 侦测该文件名是否存在且具有 “SGID” 的权限? | -k | 侦测该文件名是否存在且具有 “sticky bit” 的权限? | -s | 侦测该文件名是否存在且为 “非空白文件”? | 3.两个文件的比较 | | -nt | (newer than)判断 file1 是否比 file2 新 | -ot | (older than)判断 file1 是否比 file2 旧 | -ef | 判断 file1 与 file2 是否为同一个文件,可用在判断 hard link 上。主要意义在于判断两个文件是否均指向同一个 inode | 4.关于两个整数之间的判定 | | -eq | 两数值相等(equal) | -ne | 两数值不等(not equal) | -gt | n1 大于 n2(greater than) | -lt | n1 小于 n2(less than) | -ge | n1 大于等于 n2(greater than or equal) | -le | n1 小于等于 n2(less than or equal) | 5.判定字符串的数据 | | test -z string | 判定字符串是否为 0?若 string 为空字符串,则为 true | test -n string | 判定字符串是否非为 0?若 string 为空字符串,则为 false | test str1 == str2 | 判定 str1 是否等于 str2,若相等,则返回 true | test str1 != str2 | 判定 str1 是否不等于 str2,若相等,则返回 false | 6.多重条件判定 | | -a | (and)两情况同时成立! | -o | (or)两情况任何一个成立! | ! | 反相情况 |
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
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
test ! -e ${filename} && echo "The filename '${filename}' DO NOT exist" && exit 0
test -f ${filename} && filetype="regular file"
test -d ${filename} && filetype="directory"
test -r ${filename} && perm="readable"
test -w ${filename} && perm="${perm} writable"
test -x ${filename} && perm="${perm} executable"
echo "The filename: ${filename} is a ${filetype}"
echo "And the permission for you are : ${perm}"
[root@MiWiFi-R4A-srv bash]
[root@MiWiFi-R4A-srv bash]
Please input a filename, I will check the filename's type and permission.
Input a filename : hello.sh
The filename: hello.sh is a regular file
And the permission for you are : readable writable
|