# bash /data/shell/install_httpd.sh # curl 127.0.0.1 it works! shell study
顺序执行编写nginx编译安装脚本:
1 2 3 4 5 6 7 8 9 10
# systemctl stop httpd # vim /data/shell/install_nginx.sh yum install -y wget gcc pcre pcre-devel zlib zlib-devel cd /usr/local/src/ wget http://nginx.org/download/nginx-1.12.2.tar.gz tar -xzvf nginx-1.12.2.tar.gz cd nginx-1.12.2 ./configure --prefix=/usr/local/nginx make make install
# vim /data/shell/myvar.sh name="student" echo "my name is $name" #拼接成功 echo 'my name is $name' #单引号里面无法使用变量 echo "my name is $name666" #拼接失败 echo "my name is ${name}666" #大括号拼接成功 echo "my name is 666$name" #拼接成功
1 2 3 4 5 6
# bash /data/shell/myvar.sh my name is student my name is $name my name is my name is student666 my name is 666student
加引号和不加引号的区别,推荐加引号:
1 2
# echo 1 2 3 1 2 3
相当于echo跟三个参数:
1 2
# echo "1 2 3" 1 2 3
加引号脚本:
1 2 3 4
# vim /data/shell/myvar.sh number="1 2 3" echo $number echo "$number"
# vim /data/shell/install_nginx.sh nginxdownloadurl="http://nginx.org/download/nginx-1.12.2.tar.gz" yum install -y wget gcc pcre pcre-devel zlib zlib-devel cd /usr/local/src/ wget "$nginxdownloadurl" tar -zxvf nginx-1.12.2.tar.gz cd nginx-1.12.2 ./configure --prefix=/usr/local/nginx make make install
# ls / bin boot data dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var # echo $? 0 # ls /nononono ls: cannot access /nononono: No such file or directory # echo $? 2
自编写shell脚本如何设置返回值:
显示使用exit。
没有使用exit的话,以最后一条命令的返回值作为脚本的返回值。
1 2 3
# vim /data/shell/myreturn.sh echo "text" exit 2
1 2 3 4
# bash /data/shell/myreturn.sh text # echo $? 2
bash shell条件判断的语法:
1 2 3 4
# 格式一 if 条件; then 代码 fi
1 2 3 4 5 6
# 格式二 if 条件; then 代码 else 代码 fi
条件可以有数字判断、字符串判断、文件判断等。
条件判断之数字判断语法:
$number1 -eq $nubmer2:是否相等,equal。
$number1 -ne $nubmer2:是否不相等,not equal。
$number1 -gt $nubmer2:是否大于,greater than。
$number1 -ge $nubmer2:是否大于等于,greater or equal。
$number1 -lt $nubmer2:是否小于,less than。
$number1 -le $nubmer2:是否小于等于,less or equal 。
test命令或者[ ]命令可测试判断,返回0代表判断成立,返回非0代表判断不成立:
1 2 3 4 5 6
# test 2 -eq 2 # echo $? 0 # test 3 -eq 2 # echo $? 1
编程中习惯使用[ ]中括号:
1 2 3
# [ 2 -eq 2 ] # echo $? 0
最简单的条件判断案例:
1 2 3 4 5 6 7
# vim /data/shell/myif.sh number1=3 number2=3 if [ $number1 -eq $number2 ]; then echo "$number1 equal $number2" echo "in if" fi
1 2 3
# bash /data/shell/myif.sh 3 equal 3 in if
数字判断案例,注意缩进习惯:
1 2 3 4 5 6 7 8 9 10 11
# vim /data/shell/myif.sh number1=3 number2=4 if [ $number1 -eq $number2 ]; then echo "$number1 equal $number2" echo "in if" echo "student" else echo "$number1 not equal $number2" echo "in else" fi
1 2 3
# bash /data/shell/myif.sh 3 not equal 4 in else
不同shell语法及判断实战
node1
bash shell数字判断案例:
1 2 3 4 5 6 7 8 9
# vim /data/shell/myif.sh number1=3 number2=3 if [ $number1 -eq $number2 ]; then echo "$number1 equal $number2" echo "student" else echo "$number1 not equal $number2" fi
1 2 3
# bash /data/shell/myif.sh 3 equal 3 student
为什么说每种shell的语法不一样?底下为c shell判断的语法:
1 2 3 4 5 6 7 8
# yum install -y tcsh # vim /data/shell/mycif.sh if ( 3 == 3 ) then echo "3 equal 3" echo "student" else echo "in else" endif
# yum install -y nmap # nc -zv 127.0.0.1 22 Ncat: Version 7.50 ( https://nmap.org/ncat ) Ncat: Connected to 127.0.0.1:22. Ncat: 0 bytes sent, 0 bytes received in 0.04 seconds. # echo $? 0 # nc -zv 127.0.0.1 80 Ncat: Version 7.50 ( https://nmap.org/ncat ) Ncat: Connection refused. # echo $? 1 # nc -w 2 -zv www.baidu.com 81 Ncat: Version 7.50 ( https://nmap.org/ncat ) Ncat: Connection to 220.181.38.149 failed: Connection timed out. Ncat: Trying next address... Ncat: Connection to 220.181.38.150 failed: Connection timed out. Ncat: Trying next address... Ncat: Connection to 240e:83:205:5a:0:ff:b05f:346b failed: Network is unreachable. Ncat: Trying next address... Ncat: Network is unreachable. # echo $? 1
-z:测试端口连接状态。
-v:输出详细的状态。
-w:设置超时时间,返回值非0。
脚本,判断nginx是否存活,不存活则启动:
1 2 3 4 5 6 7 8 9 10 11
# vim /data/shell/detect_nginx.sh myip=127.0.0.1 myport=80 nc -w 2 -zv $myip $myport if [ $? -eq 0 ]; then echo "port is alived" else echo "port is not alived" echo "run nginx" /usr/local/nginx/sbin/nginx fi
1 2 3 4 5 6 7 8 9 10
# bash /data/shell/detect_nginx.sh Ncat: Version 7.50 ( https://nmap.org/ncat ) Ncat: Connection refused. port is not alived run nginx # bash /data/shell/detect_nginx.sh Ncat: Version 7.50 ( https://nmap.org/ncat ) Ncat: Connected to 127.0.0.1:80. Ncat: 0 bytes sent, 0 bytes received in 0.01 seconds. port is alived
shell条件判断之字符串判断
node1
条件判断语法:
1 2 3 4 5
if 条件; then 条件成立执行的命令,可以有多个命令 else 条件不成立执行的命令,可以多个命令 fi
# vim /data/shell/mystrapp.sh softpack="pcre-devel" soft_result=$(rpm -qa $softpack) if [ -z "$soft_result" ]; then echo "${softpack} is not find" yum install -y ${softpack} else echo "${softpack} is find" fi
# vim /data/shell/filetest.sh filename="/etc/passwd" if [ -f "$filename" ]; then echo "$filename is a file" else echo "$filename is not a file" fi
1 2
# bash /data/shell/filetest.sh /etc/passwd is a file
nginx安装脚本改善,判断是否已经安装nginx:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# vim /data/shell/install_nginx.sh if [ -d "/usr/local/nginx" ]; then echo "nginx is installed. exit" exit 1 fi nginxdownloadurl="http://nginx.org/download/nginx-1.12.2.tar.gz" yum install -y wget gcc pcre pcre-devel zlib zlib-devel cd /usr/local/src/ wget "$nginxdownloadurl" tar xzvf nginx-1.12.2.tar.gz cd nginx-1.12.2 ./configure --prefix=/usr/local/nginx make make install
# vim /data/shell/myif.sh name="nonono" if [ "$name" == "student" ] || [ "$name" == "teacher" ]; then echo "$name is my want" else echo "in else" fi
1 2
# bash /data/shell/myif.sh in else
复杂判断使用,与判断:
1 2 3 4 5 6 7 8
# vim /data/shell/myif.sh age=80 if [ $age -gt 10 ] && [ $age -lt 75 ]; then echo "age > 10 and age < 75" echo "working" else echo "in else" fi
1 2
# bash /data/shell/myif.sh in else
多复杂判断:
1 2 3 4 5 6 7
# vim /data/shell/myif.sh age=0 if [ $age -gt 2 ] && [ $age -lt 10 ] || [ $age -eq 100 ]; then echo "age is > 2 and age is < 10 or age == 100" else echo "in else" fi
# rm -rf /usr/local/nginx/ /usr/local/src/nginx* # vim /data/shell/install_nginx.sh if [ -e "/usr/local/nginx" ]; then echo "nginx is installed. exit script" exit 1 fi nginxdownloadurl="http://nginx.org/download/nginx-1.12.2.tar.gz" yum install - wget gcc pcre pcre-devel zlib zlib-devel cd /usr/local/src/ wget "$nginxdownloadurl" tar -zxvf nginx-1.12.2.tar.gz cd nginx-1.12.2 ./configure --prefix=/usr/local/nginx && make && make install
1
# bash /data/shell/install_nginx.sh
shell多重判断及优化
node1
多重判断语法elif,else if:
1 2 3 4 5 6 7 8 9
if 条件1; then 命令,条件1成立执行。 elif 条件2; then 命令,条件1不成立,条件2成立执行。 elif 条件3; then 命令,条件1不成立,条件2不成立,条件3成立执行。 else 命令,以上条件都不成立执行。 fi
案例如下,只能进入一个命令块:
1 2 3 4 5 6 7 8 9 10
# vim /data/shell/myifif.sh number1=10 if [ $number1 -le 0 ]; then echo "$number1 <= 0" elif [ $number1 -le 10 ]; then echo "$number1 > 0" echo "$number1 <= 10" else echo "$number1 > 10" fi
1 2 3
# bash /data/shell/myifif.sh 10 > 0 10 <= 10
字符串案例:
1 2 3 4 5 6 7 8 9
# vim /data/shell/myifif.sh choice="No" if [ "$choice" == "no" ] || [ "$choice" == "No" ]; then echo "choice is no" elif [ "$choice" == "yes" ]; then echo "choice is yes" else echo "not no not yes" fi
1 2
# bash /data/shell/myifif.sh choice is no
if做多重判断有个问题,就是当条件比较多的时候比较麻烦,可以借用case去改善它。
case多重判断语法,case还支持正则,后续会讲解正则:
1 2 3 4 5 6 7 8 9 10 11 12
# vim /data/shell/myifif.sh choice="student" case "$choice" in "yes" | "Yes") echo "in yes";; "no" | "No") echo "in no";; "student" | "teacher") echo "in student";; *) echo "in other other";; esac
1 2
# bash /data/shell/myifif.sh in student
shell读取用户输入
读取用户输入:
选择性输入,例如yes or no。
密码输入,不适合回显。
node1
read命令读取用户输入,输入的内容放到变量里:
1 2 3 4 5
# vim /data/shell/myread.sh read name echo "read name, name is $name" read age echo "read age, age is $age"
1 2 3 4 5
# bash /data/shell/myread.sh abc read name, name is abc 123 read age, age is 123
read命令的返回值,中断为非0:
1 2 3 4
# read name ^C # echo $? 130
read -p选项可提示用户输入什么内容:
1 2 3 4 5
# vim /data/shell/myread.sh read -p "Please input your name: " name echo "read name, name is $name" read -p "Please input your age: " age echo "read age, age is $age"
1 2 3 4 5
# bash /data/shell/myread.sh Please input your name: abc read name, name is abc Please input your age: 123 read age, age is 123
read -s选项输入密码,输入不显示:
1 2 3
# vim /data/shell/mypwd.sh read -s -p "Please input your password: " mypwd echo "read pwd, pwd is $mypwd"
1 2
# bash /data/shell/mypwd.sh Please input your password: read pwd, pwd is 123
更改nginx安装脚本,支持输入安装目录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# rm -rf /usr/local/nginx/ /usr/local/src/nginx* # vim /data/shell/install_nginx.sh read -p "Please input you installpath: " installpath if [ -e "$installpath" ]; then echo "nginx is installed. exit script" exit 1 fi nginxdownloadurl="http://nginx.org/download/nginx-1.12.2.tar.gz" yum install -y wget gcc pcre pcre-devel zlib zlib-devel cd /usr/local/src/ wget "$nginxdownloadurl" tar xzvf nginx-1.12.2.tar.gz cd nginx-1.12.2 ./configure --prefix=$installpath && make && make install
1 2
# bash /data/shell/install_nginx.sh Please input you installpath: /usr/local/nginx
# yum install -y bc # echo "scale=2; 5/3.0" | bc 1.66
shell脚本传参,使用以下变量接收传入的参数:
echo $0:脚本名。
echo $1:第一个参数值。
echo $2:第二个参数值。
echo $n:第n个参数值。
echo $#:参数的个数。
echo $$:进程pid。
echo $@:所有参数。
shell脚本传参:
1 2 3 4 5 6 7 8 9
# vim /data/shell/myparam.sh myscriptname=$0 mycity=$1 myname=$2 myage=$3 echo "script name is $myscriptname" echo "city is $mycity" echo "name is $myname" echo "param length $#"
1 2 3 4 5
# bash /data/shell/myparam.sh zbc student 123 script name is /data/shell/myparam.sh city is zbc name is student param length 3
shell传参数的方式安装nginx:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# rm -rf /usr/local/src/nginx-* /usr/local/nginx # vim /data/shell/install_nginx.sh if [ $# -eq 0 ]; then echo "no parameter" exit 1 fi installpath=$1 if [ -e "$installpath" ]; then echo "nginx is installed. exit script" exit 1 fi nginxdownloadurl="http://nginx.org/download/nginx-1.12.2.tar.gz" yum install -y wget gcc pcre pcre-devel zlib zlib-devel cd /usr/local/src/ wget "$nginxdownloadurl" tar -zxvf nginx-1.12.2.tar.gz cd nginx-1.12.2 ./configure --prefix=$installpath && make && make install
# bash /data/shell/myfor.sh read it. line is root:x:0:0:root:/root:/bin/bash read it. line is bin:x:1:1:bin:/bin:/sbin/nologin read it. line is daemon:x:2:2:daemon:/sbin:/sbin/nologin read it. line is adm:x:3:4:adm:/var/adm:/sbin/nologin read it. line is lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin read it. line is sync:x:5:0:sync:/sbin:/bin/sync read it. line is shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown read it. line is halt:x:7:0:halt:/sbin:/sbin/halt read it. line is mail:x:8:12:mail:/var/spool/mail:/sbin/nologin read it. line is operator:x:11:0:operator:/root:/sbin/nologin read it. line is games:x:12:100:games:/usr/games:/sbin/nologin read it. line is ftp:x:14:50:FTP read it. line is User:/var/ftp:/sbin/nologin read it. line is nobody:x:99:99:Nobody:/:/sbin/nologin read it. line is systemd-network:x:192:192:systemd read it. line is Network read it. line is Management:/:/sbin/nologin read it. line is dbus:x:81:81:System read it. line is message read it. line is bus:/:/sbin/nologin read it. line is polkitd:x:999:998:User read it. line is for read it. line is polkitd:/:/sbin/nologin read it. line is sshd:x:74:74:Privilege-separated read it. line is SSH:/var/empty/sshd:/sbin/nologin read it. line is postfix:x:89:89::/var/spool/postfix:/sbin/nologin read it. line is chrony:x:998:996::/var/lib/chrony:/sbin/nologin read it. line is apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
解决上述问题需要改变IFS内置变量:
1 2 3 4 5 6 7
# vim /data/shell/myfor.sh OLDIFS=$IFS IFS=$'\n' for line in $(cat /etc/passwd); do echo "read it. line is $line" done IFS=$OLDIFS
# bash /data/shell/myfor.sh read it. line is root:x:0:0:root:/root:/bin/bash read it. line is bin:x:1:1:bin:/bin:/sbin/nologin read it. line is daemon:x:2:2:daemon:/sbin:/sbin/nologin read it. line is adm:x:3:4:adm:/var/adm:/sbin/nologin read it. line is lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin read it. line is sync:x:5:0:sync:/sbin:/bin/sync read it. line is shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown read it. line is halt:x:7:0:halt:/sbin:/sbin/halt read it. line is mail:x:8:12:mail:/var/spool/mail:/sbin/nologin read it. line is operator:x:11:0:operator:/root:/sbin/nologin read it. line is games:x:12:100:games:/usr/games:/sbin/nologin read it. line is ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin read it. line is nobody:x:99:99:Nobody:/:/sbin/nologin read it. line is systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin read it. line is dbus:x:81:81:System message bus:/:/sbin/nologin read it. line is polkitd:x:999:998:User for polkitd:/:/sbin/nologin read it. line is sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin read it. line is postfix:x:89:89::/var/spool/postfix:/sbin/nologin read it. line is chrony:x:998:996::/var/lib/chrony:/sbin/nologin read it. line is apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
应用:使用for循环批量判断包是否已安装:
1 2 3 4 5 6 7 8 9
# vim /data/shell/mypackcheck.sh for softpack in wget gcc pcre pcre-devel zlib zlib-devel; do soft_result=$(rpm -qa $softpack) if [ -z "$soft_result" ];then yum install -y $softpack else echo "$softpack is installed" fi done
1 2 3 4 5 6 7
# bash /data/shell/mypackcheck.sh wget is installed gcc is installed pcre is installed pcre-devel is installed zlib is installed zlib-devel is installed
循环的break和continue
shell循环中的break和continue,语法适用于while、for:
break直接结束循环,循环立即退出。
continue可以用来跳过一次循环,跳过后循环继续,直到循环停止。
node1
break语法:
1 2 3 4 5 6 7
# vim /data/shell/mybreak.sh for line in student teacher classmate roommate workmate; do echo $line if [ "$line" == "teacher" ];then break fi done
1 2 3
# bash /data/shell/mybreak.sh student teacher
continue用来跳过一次循环:
1 2 3 4 5 6 7
# vim /data/shell/mycontinue.sh for line in student teacher classmate roommate workmate; do if [ "$line" == "teacher" ];then continue fi echo $line done
# vim /data/shell/myfunc.sh function echo_hello() { echo "hello world" echo -e "student\n" } echo "call function one" echo_hello echo "call function two" echo_hello
1 2 3 4 5 6 7 8
# bash /data/shell/myfunc.sh call function one hello world student
call function two hello world student
函数支持传递参数:
$1:第一个参数。
$2:第二个参数。
$n:第n个参数。
函数传递参数使用:
1 2 3 4 5 6 7 8
# vim /data/shell/myfunc.sh function echo_name_age() { name=$1 age=$2 echo "name is $name.age is $age" } echo "run function with parameters" echo_name_age ABC 123
1 2 3
# bash /data/shell/myfunc.sh run function with parameters name is ABC.age is 123
函数的退出码和应用
脚本的退出码:
使用exit或者以最后命令的退出码为准。
函数使用return定义退出码,0表示正常,非0表示异常。
无return以最后一条命令。
node1
1 2 3 4 5 6 7 8 9
# vim /data/shell/myreturn.sh function echo_name_age() { name=$1 age=$2 echo "name is $name, age is $age" return 6 } echo_name_age abc 123 echo $?
1 2 3
# bash /data/shell/myreturn.sh name is abc, age is 123 6
使用函数检查rpm包是否已安装:
1 2 3 4 5 6 7 8 9 10 11 12 13
# vim /data/shell/myreturn.sh function check_rpm_package() { package_name=$1 result=$(rpm -qa $package_name) if [ -z "$result" ]; then yum install -y $package_name else echo "$package_name is installed" fi } for packname in pcre-devel pcre zlib zlib-devel; do check_rpm_package $packname done
1 2 3 4 5
# bash /data/shell/myreturn.sh pcre-devel is installed pcre is installed zlib is installed zlib-devel is installed
# cat /tmp/student | awk '{print NR,$0,$1}' 1 tudent1 31 hangzhou tudent1 2 student2 22 shenzhen student2 3 student3 29 shanghai student3 4 zhangsan1 33 hangzhou zhangsan1 5 zhangsan2 34 foreign zhangsan2 6 zhangsan3 18 beijing zhangsan3 # cat /tmp/student | awk '{print $1,$2}' tudent1 31 student2 22 student3 29 zhangsan1 33 zhangsan2 34 zhangsan3 18 # cat /tmp/student |awk '{print "name is "$1", " "age is "$2"."}' name is tudent1, age is 31. name is student2, age is 22. name is student3, age is 29. name is zhangsan1, age is 33. name is zhangsan2, age is 34. name is zhangsan3, age is 18.
# vim /tmp/student Port 22 Port 22 Port 22 PermitRootLogin yes Port 22 PasswordAuthentication yes ListenAddress 10.175.201.36 sedsedsed //note nouse Port
全局替换:
1 2 3 4 5 6 7 8 9 10
# cat /tmp/student | sed 's/22/1111/g' Port 1111 Port 1111 Port 1111 PermitRootLogin yes Port 1111 PasswordAuthentication yes ListenAddress 10.175.201.36 sedsedsed //note nouse Port
每行第一次出现替换:
1 2 3 4 5 6 7 8 9 10
# cat /tmp/student | sed 's/22/1111/' Port 1111 Port 22 Port 22 PermitRootLogin yes Port 1111 PasswordAuthentication yes ListenAddress 10.175.201.36 sedsedsed //note nouse Port
# cat /tmp/student | sed 's/ListenAddress .*/ListenAddress 192.168.0.1/' Port 22 Port 22 Port 22 PermitRootLogin yes Port 22 PasswordAuthentication yes ListenAddress 192.168.0.1 sedsedsed //note nouse Port # cat /tmp/student | sed -r 's/(sed){3}/\1/' Port 22 Port 22 Port 22 PermitRootLogin yes Port 22 PasswordAuthentication yes ListenAddress 10.175.201.36 sed //note nouse Port
sed分隔符可以有多种选择,一般都用/:
1 2 3 4 5 6 7 8 9 10
# cat /tmp/student |sed 's#//#;#' Port 22 Port 22 Port 22 PermitRootLogin yes Port 22 PasswordAuthentication yes ListenAddress 10.175.201.36 sedsedsed ;note nouse Port
过滤加替换:
1 2 3 4 5 6 7 8 9 10
# cat /tmp/student | sed '1,2s/22/1111/g' Port 1111 Port 1111 Port 1111 PermitRootLogin yes Port 22 PasswordAuthentication yes ListenAddress 10.175.201.36 sedsedsed //note nouse Port
正则过滤加替换:
1 2 3 4 5 6 7 8 9 10
# cat /tmp/student | sed '/^Port/s/Port/PORT/g' PORT 22 PORT 22 PORT 22 PermitRootLogin yes PORT 22 PasswordAuthentication yes ListenAddress 10.175.201.36 sedsedsed //note nouse Port
sed支持直接更改文本文件,使用-i选项:
1 2 3 4 5 6 7 8 9 10 11 12
# sed 's/22/1111/g' /tmp/student Port 1111 Port 1111 Port 1111 PermitRootLogin yes Port 1111 PasswordAuthentication yes ListenAddress 10.175.201.36 sedsedsed //note nouse Port # sed -i 's/22/1111/g' /tmp/student # sed -i '/PermitRootLogin/a PermitStudent' /tmp/student
# vim /data/shell/test.sh rm -rf /opt/nginx installpath=/opt/nginx if [ -e "$installpath" ]; then echo "nginx is installed. exit script" exit 1 fi nginxdownloadurl="http://nginx.org/download/nginx-1.14.1.tar.gz" yum install -y wget gcc pcre pcre-devel zlib zlib-devel cd /usr/local/src/ wget "$nginxdownloadurl" targzname=$(echo $nginxdownloadurl | sed 's#.*/##') tar xzvf $targzname dirname=$(echo $targzname | sed 's/.tar.gz//') cd $dirname ./configure --prefix=$installpath && make && make install
1
# bash /data/shell/test.sh
find文件查找入门
find简单介绍:
find命令用来搜索指定文件。
搜索到指定文件后可执行某些动作,例如rm操作。
node1
文件准备:
1 2 3 4 5 6 7
# rm -rf /tmp/student; mkdir /tmp/student; cd /tmp/student # for line in $(seq 10);do touch file_$line mkdir dir_$line done # ln -s /tmp/student/file_9 /tmp/student/file_link # chown nobody:nobody file_7
# find /tmp/student/ -type f -name "blank*" | xargs ls -l ls: cannot access /tmp/student/blank: No such file or directory ls: cannot access student: No such file or directory
使用-print0和-0代表以\0作为分隔符:
1 2 3 4
# find /tmp/student/ -type f -name "blank*" -print0 | xargs -0 ls -l -rw-r--r-- 1 root root 0 Nov 2 06:30 /tmp/student/blank student # find /tmp/student/ -type f -print0 | xargs -0 grep 'abc' /tmp/student/file_6:abc
统计各个字符出现的次数
node1
统计基础:
1 2 3 4 5
# cat /etc/ssh/sshd_config | grep -o a # cat /etc/ssh/sshd_config | grep -o a | wc 153 153 306 # cat /etc/ssh/sshd_config | grep -o a | wc -l 153
使用{a..z}可以循环获取26个小写字母:
1 2 3 4
# vim /data/shell/countchar.sh for i in {a..z}; do echo "read it $i" done
# bash /data/shell/countchar.sh read it a read it b read it c read it d read it e read it f read it g read it h read it i read it j read it k read it l read it m read it n read it o read it p read it q read it r read it s read it t read it u read it v read it w read it x read it y read it z
循环统计每个字母出现的次数:
1 2 3 4
# vim /data/shell/countchar.sh for i in {a..z}; do cat /etc/ssh/sshd_config | grep -o $i | wc -l done
# bash /data/shell/countchar.sh a 153 b 34 c 86 d 94 e 324 f 30 g 46 h 116 i 178 j 1 k 24 l 88 m 39 n 223 o 234 p 59 q 0 r 138 s 271 t 240 u 81 v 31 w 37 x 13 y 74 z 8
统计大写字母:
1 2 3 4 5
# vim /data/shell/countchar.sh for i in {A..Z}; do result=`cat /etc/ssh/sshd_config | grep -o $i | wc -l` echo -e "$i\t$result" done
# bash /data/shell/countchar.sh A 68 B 3 C 38 D 10 E 33 F 17 G 14 H 13 I 23 J 0 K 17 L 38 M 24 N 14 O 11 P 44 Q 0 R 20 S 37 T 29 U 18 V 2 W 1 X 5 Y 4 Z 0
统计每个数字:
1 2 3 4 5
# vim /data/shell/countchar.sh for i in {0..9}; do result=`cat /etc/ssh/sshd_config | grep -o $i | wc -l` echo -e "$i\t$result" done
# vim /data/shell/countchar.sh for i in {0..9} {a..z} {A..Z}; do countresult=$(cat /etc/ssh/sshd_config | grep -o $i | wc -l) echo -e "$i\t$countresult" done
# bash /data/shell/countchar.sh 0 16 1 18 2 8 3 3 4 1 5 5 6 2 7 0 8 1 9 1 a 153 b 34 c 86 d 94 e 324 f 30 g 46 h 116 i 178 j 1 k 24 l 88 m 39 n 223 o 234 p 59 q 0 r 138 s 271 t 240 u 81 v 31 w 37 x 13 y 74 z 8 A 68 B 3 C 38 D 10 E 33 F 17 G 14 H 13 I 23 J 0 K 17 L 38 M 24 N 14 O 11 P 44 Q 0 R 20 S 37 T 29 U 18 V 2 W 1 X 5 Y 4 Z 0
# vim /data/shell/serverlist node1 10.80.10.1 node2 10.80.10.2
批量修改主机名:
1 2 3 4 5 6 7 8 9 10 11 12 13
# vim /data/shell/allserver.sh OLDIFS=$IFS IFS=$'\n'
for line in $(cat /data/shell/serverlist); do myhost=$(echo $line | awk '{print $1}') myip=$(echo $line | awk '{print $2}') echo "myhost is $myhost. myip is $myip" ssh $myip "hostnamectl set-hostname $myhost" ssh $myip "echo $myip $myhost >> /etc/hosts" done
IFS=$OLDIFS
1 2 3
# bash /data/shell/allserver.sh myhost is node1. myip is 10.80.10.1 myhost is node2. myip is 10.80.10.2
批量执行shell命令:
1 2 3 4 5 6 7 8 9 10 11 12
# vim /data/shell/allserver.sh OLDIFS=$IFS IFS=$'\n'
for line in $(cat /data/shell/serverlist); do myhost=$(echo $line | awk '{print $1}') myip=$(echo $line | awk '{print $2}') echo "myhost is $myhost. myip is $myip" ssh $myip "uptime; ip addr show" done
# bash /data/shell/allserver.sh myhost is node1. myip is 10.80.10.1 Dec 9 22:22:33 node1 systemd: Started Session 19 of user root. Dec 9 22:22:33 node1 systemd-logind: Removed session 19. Dec 9 22:22:33 node1 systemd-logind: New session 20 of user root. Dec 9 22:22:33 node1 systemd: Started Session 20 of user root. Dec 9 22:22:33 node1 systemd-logind: Removed session 20. Dec 9 22:22:56 node1 systemd-logind: New session 21 of user root. Dec 9 22:22:56 node1 systemd: Started Session 21 of user root. Dec 9 22:22:57 node1 systemd-logind: Removed session 21. Dec 9 22:23:19 node1 systemd-logind: New session 22 of user root. Dec 9 22:23:19 node1 systemd: Started Session 22 of user root. myhost is node2. myip is 10.80.10.2 Dec 9 22:22:34 node2 systemd-logind: Removed session 14. Dec 9 22:22:34 node2 systemd: Removed slice User Slice of root. Dec 9 22:22:57 node2 systemd: Created slice User Slice of root. Dec 9 22:22:57 node2 systemd-logind: New session 15 of user root. Dec 9 22:22:57 node2 systemd: Started Session 15 of user root. Dec 9 22:22:57 node2 systemd-logind: Removed session 15. Dec 9 22:22:57 node2 systemd: Removed slice User Slice of root. Dec 9 22:23:20 node2 systemd: Created slice User Slice of root. Dec 9 22:23:20 node2 systemd-logind: New session 16 of user root. Dec 9 22:23:20 node2 systemd: Started Session 16 of user root.
for line in $(cat /data/shell/serverlist); do myhost=$(echo $line | awk '{print $1}') myip=$(echo $line | awk '{print $2}') echo "myhost is $myhost. myip is $myip" scp /tmp/student.txt $myip:/usr/local/src/ done
IFS=$OLDIFS
1 2 3 4 5 6 7
# bash /data/shell/allserver.sh myhost is node1. myip is 10.80.10.1 student.txt 100% 9 3.5KB/s 00:00 myhost is node2. myip is 10.80.10.2 student.txt 100% 9 1.5KB/s 00:00 # ls /usr/local/src/student.txt /usr/local/src/student.txt
批量拉取文件:
1 2 3 4 5 6 7 8 9 10 11 12
# vim /data/shell/allserver.sh OLDIFS=$IFS IFS=$'\n'
for line in $(cat /data/shell/serverlist); do myhost=$(echo $line | awk '{print $1}') myip=$(echo $line | awk '{print $2}') echo "myhost is $myhost. myip is $myip" scp $myip:/usr/local/src/student.txt /tmp/student.txt.$myip done
IFS=$OLDIFS
1 2 3 4 5 6 7
# bash /data/shell/allserver.sh myhost is node1. myip is 10.80.10.1 student.txt 100% 9 3.6KB/s 00:00 myhost is node2. myip is 10.80.10.2 student.txt 100% 9 2.7KB/s 00:00 # ls /tmp/ student.txt student.txt.10.80.10.1 student.txt.10.80.10.2 test
# vim /tmp/urls www.baidu.com www.baidu.com:82 www.baidu.com:81 127.0.0.1 127.0.0.1:81
批量探测http接口:
1 2 3 4 5 6 7 8 9
# vim /data/shell/urls for one_url in $(cat /tmp/urls); do curl -s -m 2 $one_url > /dev/null if [ $? -eq 0 ];then echo "$one_url is normal" else echo "$one_url is unnormal" fi done
1 2 3 4 5 6
# bash /data/shell/urls www.baidu.com is normal www.baidu.com:82 is unnormal www.baidu.com:81 is unnormal 127.0.0.1 is normal 127.0.0.1:81 is unnormal
shell多进程简单实现
多线程fifo的那个理解起来会比较难。上万个http接口探测的话很慢。
node1
以sleep代替响应慢的情况。
1 2 3 4 5
# vim /data/shell/test.sh for number in $(seq 6); do echo $number sleep 2 done
1 2 3 4 5 6 7
# bash /data/shell/test.sh 1 2 3 4 5 6
多进程的方式&,使用wait等待所有进程运行结束:
1 2 3 4 5 6 7 8
# vim /data/shell/test.sh for number in $(seq 6); do ( echo $number sleep 2 ) & done wait
1 2 3 4 5 6 7
# bash /data/shell/test.sh 4 3 5 1 6 2
进程数不控制的话,容易导致系统崩溃:
1 2 3 4 5 6 7 8
# vim /data/shell/test.sh for number in $(seq -w 100); do ( echo $number sleep 10 ) & done wait
1
# bash /data/shell/test.sh
支持控制进程数量,并发进程10个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# vim /data/shell/test.sh i=0 for number in $(seq 33); do let i=$i+1 let j=$i%10 ( echo $number sleep 5 ) & if [ $j -eq 0 ];then wait fi done wait
# vim /data/shell/test.sh i=0 for one_url in $(cat /tmp/urls); do let i=$i+1 let j=$i%12 ( curl -m 2 -s $one_url > /dev/null if [ $? -eq 0 ];then echo "$one_url is normal" else echo "$one_url is unnormal" fi ) & if [ $j -eq 0 ];then wait fi done wait