Appearance
shell脚本
关于引号
单引号:
可以说是所见即所得:即将单引号内的内容原样输出,或者描述为单引号里面看见的是什么就会输出什么。
双引号:
把双引号内的内容输出出来;如果内容中有命令,变量等,会先把变量,命令解析出结果,然后在输出最终内容来。
双引号内命令或变量的写法为命令或变量或$(命令或变量)。
无引号:
把内容输出出来,可能不会讲含有空格的字符串视为一个整体输出;
如果内容中有命令、变量等,会先把变量、命令解析结果,然后在输出最终内容来;
如果字符串中带有空格等特殊字符,则不能完整的输出,需要改加双引号,一般连续的字符串,数字,路径等可以用,不过最好用双引号替代之
sh文件获取当前绝对路径
获取sh文件所在的绝对路径
shell
filepath=$(cd "$(dirname "$0")"; pwd)sh根据端口查进程
下面是一个sh示例,需要输入一个参数,即端口。可能会有重复打印
shell
#!/bin/bash
# 检查是否提供了端口号作为参数
if [ -z "$1" ]; then
echo "请提供端口号作为参数!"
exit 1
fi
# 设置端口号变量
PORT=$1
# 使用 netstat 命令获取端口信息
# 注意: netstat -tulnp 可以获取到 PID,而 PID 可以用于进一步查找程序名称
# 过滤输出只保留感兴趣的行
netstat -tulnp | grep ":$PORT" | awk '{print $7}' | cut -d'/' -f1 | while read -r pid; do
echo "Process ID: $pid"
# 使用 ps 命令根据 PID 查找程序名称
ps -p $pid -o pid,command,cmd | while read -r line; do
echo "$line"
done
doneif判断
if的基本语法
shell
if [ command ];then
符合该条件执行的语句
elif [ command ];then
符合该条件执行的语句
else
符合该条件执行的语句
fi文件/文件夹判断
shell
[ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真。
[ -c FILE ] 如果 FILE 存在且是一个字特殊文件则为真。
[ -d DIR ] 如果 FILE 存在且是一个目录则为真。
[ -e FILE ] 如果 FILE 存在则为真。
[ -f FILE ] 如果 FILE 存在且是一个普通文件则为真。
[ -g FILE ] 如果 FILE 存在且已经设置了SGID则为真。
[ -k FILE ] 如果 FILE 存在且已经设置了粘制位则为真。
[ -p FILE ] 如果 FILE 存在且是一个名字管道(F如果O)则为真。
[ -r FILE ] 如果 FILE 存在且是可读的则为真。
[ -s FILE ] 如果 FILE 存在且大小不为0则为真。
[ -t FD ] 如果文件描述符 FD 打开且指向一个终端则为真。
[ -u FILE ] 如果 FILE 存在且设置了SUID (set user ID)则为真。
[ -w FILE ] 如果 FILE存在且是可写的则为真。
[ -x FILE ] 如果 FILE 存在且是可执行的则为真。
[ -O FILE ] 如果 FILE 存在且属有效用户ID则为真。
[ -G FILE ] 如果 FILE 存在且属有效用户组则为真。
[ -L FILE ] 如果 FILE 存在且是一个符号连接则为真。
[ -N FILE ] 如果 FILE 存在 and has been mod如果ied since it was last read则为真。
[ -S FILE ] 如果 FILE 存在且是一个套接字则为真。
[ FILE1 -nt FILE2 ] 如果 FILE1 has been changed more recently than FILE2, or 如果 FILE1 exists and FILE2 does not则为真。
[ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 要老, 或者 FILE2 存在且 FILE1 不存在则为真。
[ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则为真。字符串判断
shell
[ -z STRING ] 如果STRING的长度为零则为真 ,即判断是否为空,空即是真;
[ -n STRING ] 如果STRING的长度非零则为真 ,即判断是否为非空,非空即是真;
[ STRING1 = STRING2 ] 如果两个字符串相同则为真 ;
[ STRING1 != STRING2 ] 如果字符串不相同则为真 ;
[ STRING1 ] 如果字符串不为空则为真,与-n类似数值判断
shell
INT1 -eq INT2 INT1和INT2两数相等为真 ,=
INT1 -ne INT2 INT1和INT2两数不等为真 ,<>
INT1 -gt INT2 INT1大于INT1为真 ,>
INT1 -ge INT2 INT1大于等于INT2为真,>=
INT1 -lt INT2 INT1小于INT2为真 ,<</div>
INT1 -le INT2 INT1小于等于INT2为真,<=逻辑判断
shell
-a 与
-o 或
! 非
exp1: 如果a>b且a<c
if (( a > b )) && (( a < c ))
或者
if [[ $a > $b ]] && [[ $a < $c ]]
或者
if [ $a -gt $b -a $a -lt $c ]
exp2:如果a>b或a<c
if (( a > b )) || (( a < c ))
或者
if [[ $a > $b ]] || [[ $a < $c ]]
或者
if [ $a -gt $b -o $a -lt $c ]
"||"和"&&"在SHELL里可以用,也就是第一个写成if [ a>b && a<c ][ ]与[[ ]]
在Shell脚本中,单中括号[]和双中括号[[ ]]是两种不同的条件测试结构,它们在功能和使用场景上存在显著的区别。
单中括号[]: 单中括号是传统的POSIX风格语法,用于基本的条件测试。 它支持较少的操作符,主要处理简单的条件判断,如字符串比较和文件测试。 在单中括号内,变量需要进行引用以避免单词分割,即如果变量值包含空白符,需要用引号将变量括起来。 单中括号不支持正则表达式匹配和逻辑运算符。
双中括号[[ ]]: 双中括号是Bash特有的扩展,提供了更强大的功能和更灵活的条件判断。 它支持更复杂的表达式,包括正则表达式匹配、逻辑运算符、更丰富的字符串比较等。 在双中括号内,变量不需要引用,也不会导致错误的变量扩展。 双中括号允许使用通配符进行模式匹配,支持使用==和!=进行字符串比较,而单中括号只能使用=进行字符串比较。 使用场景:
单中括号适合基本的条件判断,如检查文件是否存在、比较两个字符串是否相等等。 双中括号适合需要更复杂逻辑判断的场景,如使用正则表达式匹配字符串模式、进行逻辑与或运算等。 总的来说,双中括号提供了更多的功能和灵活性,尤其是在处理复杂的条件判断和字符串处理时。而单中括号则更适合简单的条件测试和基本的字符串比较
加不加引号
-z 判断 变量的值,是否为空; zero = 0
- 变量的值,为空,返回0,为true
- 变量的值,非空,返回1,为false -n 判断变量的值,是否为空 name = 名字
- 变量的值,为空,返回1,为false
- 变量的值,非空,返回0,为true pid="123"
[ -z "$pid" ] 单对中括号变量必须要加双引号 [[ -z $pid ]] 双对括号,变量不用加双引号 [ -n "$pid" ] 单对中括号,变量必须要加双引号 [[ -z $pid ]] 双对中括号,变量不用加双引号
[[ ]] 双对中括号,是不能使用 -a 或者 -o的参数进行比较的
&& 并且 || 或 -a 并且 -o 或者 [[ ]] 条件判断 && 并且 || 或
[[ 5 -lt 3 || 3 -gt 6 ]] 一个条件,满足,就成立 或者的关系 [[ 5 -lt 3 || 3 -gt 6 ]] 一个条件满足,就成立 或者的关系 [[ 5 -lt 3 ]] || [[3 -gt 6 ]] [[ 5 -lt 3 ]] || [[3 -gt 6 ]] 写在外面也可以
&& 必须两个条件同时满足,和上述一样,这里想说明的问题的是:
[[ 5 -lt 3]] -o [[ 3 -gt 6 ]] [[ 5 -lt 3 -o 3 -gt 6 ]] [[ 5 -lt 3 -a 3 -gt 6 ]] [[ 5 -lt 3 -a 3 -gt 6 ]]
-a 和 -o就不成立了,是因为,[[]] 双对中括号,不能使用 -o和 -a的参数
[ ] 可以使用 -a -o的参数,但是必须在 [ ] 中括号内
[ 5 -lt 3 -o 3 -gt 2 ] 或者条件成立 [5 -lt 3 ] -o [ 3 -gt 2] 或者条件, 这个不成立,因为必须在中括号内判断
如果想在中括号外判断两个条件,必须用&& 和 || 比较 [5 -lt 3 ] || [ 3 -gt 2] [5 -gt 3 ] && [ 3 -gt 2] 成立 相对的,|| 和 && 不能在中括号内使用,只能在中括号外使用
当判断某个变量的值是否满足正则表达式的时候,必须使用[[ ]] 双对中括号
特殊变量
| 名称 | 说明 |
|---|---|
| $0 | 脚本名称 |
| $1-9 | 脚本执行时的参数1到参数9 |
| $? | 脚本的返回值 |
| $# | 脚本执行时,输入的参数的个数 |
| $@ | 输入的参数的具体内容(将输入的参数作为一个多个对象,即是所有参数的一个列表) |
| $* | 输入的参数的具体内容(将输入的参数作为一个单词) |
$@与$*的区别:
$@与$*都可以使用一个变量来来表示所有的参数内容,但这两个变量之间有一些不同之处。
$@:将输入的参数作为一个列表对象
$*:将输入的参数作为一个单词
shell
echo "脚本的名字是:"$0
n=1
echo "使用\$@的参数列表为:"$@
for temstr in "$@"
do
echo "第$n个参数是:" $temstr
let n+=1
done
n=1
echo "使用\$*的参数列表为:"$*
for temstr in "$*"
do
echo "第$n个参数是:" $temstr
let n+=1
done执行以上脚本,设为test.sh,结果应为
shell
./test.sh 1 2 3 4
脚本的名字是:./test.sh
使用$@的参数列表为:1 2 3 4
第1个参数是: 1
第2个参数是: 2
第3个参数是: 3
第4个参数是: 4
使用$*的参数列表为:1 2 3 4
第1个参数是: 1 2 3 4磁盘挂载
挂载windows共享目录
shell
mount -t cifs -o username=administrator,password=xxx //172.17.0.68/backup/WIKI /mnt/WIKI解除挂载
shell
umount /mnt/WIKI定时任务
每月最后一天执行
shell
30 23 28-31 * * [ $(date -d tomorrow +%d) -eq 1 ] && bash /path/to/your/script.sh上面的可能不太稳妥,可能由于版本原因不兼容,下面的方案更稳定。判断最后一天写在脚本中。 不妨创建一个last_day_script.sh文件,内容如下:
shell
if [ $(date -d tomorrow +%d) -eq 1 ]; then
/path/to/your/script.sh
else
echo 'not last day'
fi然后在crontab中添加如下任务:
shell
30 23 28-31 * * bash /path/to/your/last_day_script.shCPU信息
总核数 = 物理CPU个数 X 每颗物理CPU的核数 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数
查看完整信息
shell
cat /proc/cpuinfo查看物理CPU个数
shell
cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l查看每个物理CPU中core的个数(即核数)
shell
cat /proc/cpuinfo| grep "cpu cores"| uniq查看逻辑CPU的个数
shell
cat /proc/cpuinfo| grep "processor"| wc -l查看CPU信息(型号)
shell
cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c内存信息
查看内存信息
shell
cat /proc/meminfo查看机器型号(机器硬件型号)
shell
dmidecode | grep "Product Name"
# or 全部
dmidecode系统信息
如何查看Linux 内核
shell
uname -a
# or
cat /proc/version如何查看linux 系统版本
shell
# centos实测可用
cat /etc/redhat-release
# Ubuntu实测可用
lsb_release -a
cat /etc/issue