1. 数组
1
2
3
4
5
arr=(str1 str2 str3)
for i in ${arr[@]}
do
echo $i
done
  1. 预定义变量
1
2
3
4
5
6
$# 表示命令中位置参数的数量
$* 表示所有的位置参数的内容
$? 表示命令执行后的返回的状态,用于检查上一个命令的执行是否正确。在linux中,命令退出状态为0表示命令执行正确,任何非0值的表示命令执行错误。
$$ 表示当前进程的进程号
$! 表示后台运行的最后一个进程的进程号
$0 所有参数
  1. 测试语句
 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
-eq Equal to = Equal to   
-ne Not equal to != Not equal to
-lt Less than \< Less than (ASCII) *
-le Less than or equal to
-gt Greater than > Greater than (ASCII) *
-ge Greater than or equal to
re-directs output of one file to another.
-a file
True if file exists.
-b file
True if file exists and is a block special file.
-c file
True if file exists and is a character special file.
-d file
True if file exists and is a directory.
-e file
True if file exists.
-f file
True if file exists and is a regular file.
-g file
True if file exists and is set-group-id.
-h file
True if file exists and is a symbolic link.
-k file
True if file exists and its ``sticky'' bit is set.
-p file
True if file exists and is a named pipe (FIFO).
-r file
True if file exists and is readable.
-s file
True if file exists and has a size greater than zero.
-t fd True if file descriptor fd is open and refers to a terminal.
-u file
True if file exists and its set-user-id bit is set.
-w file
True if file exists and is writable.
-x file
True if file exists and is executable.
-G file
True if file exists and is owned by the effective group id.
-L file
True if file exists and is a symbolic link.
-N file
True if file exists and has been modified since it was last read.
-O file
True if file exists and is owned by the effective user id.
-S file
True if file exists and is a socket.
file1 -ef file2
True if file1 and file2 refer to the same device and inode numbers.
file1 -nt file2
True if file1 is newer (according to modification date) than file2, or if file1 exists and file2 does not.
file1 -ot file2
True if file1 is older than file2, or if file2 exists and file1 does not.
-o optname
True if the shell option optname is enabled. See the list of options under the description of the -o option to the set builtin below.
-v varname
True if the shell variable varname is set (has been assigned a value).
-z string
True if the length of string is zero.
string
-n string
True if the length of string is non-zero.
  1. 发送邮件
1
2
echo "content" | mail -s title 1248247511@qq.com
#mail 命令依赖 yum install mailx
  1. 计算
1
2
echo `expr 1 + 1`
echo "1+3","ALL" | bc
  1. 函数

函数的定义和调用

在使用一个shell函数之前,要求必须先进行定义,定义函数的语句格式如下。

function 函数名{
  操作命令
}

或者也可以简化掉function,但必须在函数名称后加小括号。

函数名(){
  操作命令
}

调用函数时,直接使用函数名称即可(不需要加小括号)

例 在脚本中定义一个help函数,当用户输入的脚本参数不是start或stop时,加载该函数并给出关于命令用法的帮助信息,否则给出对应的提示信息。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
vi help.sh
#!/bin/bash

help() {
  echo "Usage: "$0","ALL" start|stop"           //$0变量用于表示脚本文件名称
}
case "$1","ALL" in
  start)
    echo "starting..."
    ;;
  stop)
    echo "shutdown..."
    ;;
  *)
    help   //调用前面定义的help()函数并执行其中的语句
esac

chmod a+x help.sh
./help.sh start
./help.sh restart  //参数不符合要求,输出执行帮助信息
Usage: ./help.sh start|stop

函数的参数传递 在shell脚本中,已经定义的函数就相当于脚本内部设置的命令一样,也可以使用位置参数。如果函数中的命令序列能够处理这些函数,则使用参数传递功能可以实现更加灵活的应用。 例 在脚本中定义一个加法函数,用于计算两个数的和,并调用该函数分别计算12+34、56+78的和。 vi adderfun.sh

1
2
3
4
5
6
7
8
#!/bin/bash

adder() {
  echo `expr $1 + $2`
}

adder 12 34            //将12、34作为adder函数的位置变量$1$2
adder 56 78
  1. 当系统load较高时,打印当前系统的一些信息,便于排查问题。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/bin/bash

while true;do
  
  # shell不支持浮点类型,这里只能取整数
  res=$(uptime  | awk -F'average:' '{print $2}' | awk -F',' '{print $1}' | awk -F'.' '{print $1}')
  
  if [[ $res -gt 5 ]];then
    top -d 1 -n 2 >> /tmp/log
    mpstat 1 2 >> /tmp/log
  else
    :
  fi

  sleep 1

done
  1. 批量创建用户
1
2
3
4
5
6
7
for((i=1;i<=20;i++))
do
  useradd user$i
  ran=$(echo $RANDOM | md5sum | head -c 5)
  echo "user$ran" | passwd --stdin user$i
  echo "user$i    user$ran" >> /root/user.txt
done
  1. 大于15k的文件
1
2
3
4
5
for i in `ls -l /root/ | grep -v ^d |grep -v total | awk '{print $NF}'`
do
file=$(du -k /root/$i | awk '{if($1>15) print $2}')
echo $file | grep -v '^$'
done
  1. nginx日志备份
#!/bin/bash
set -euxo pipefail

time=$(date +%Y%m%d)
logpath="/usr/local/nginx/logs"

cd $logpath
mv access.log access_$time.log
mv error.log error_$time.log
kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
sleep 1
gzip access_$time.log
gzip error_$time.log

11.审计统计

#!/bin/bash

echo "审计统计详情(统计时间为昨天)"
echo ""

ip=$(ip a |grep '10\.' | awk '{print $2}')
echo "IP地址:   $ip"

/sbin/aureport -if /var/log/audit/audit.log -ts yesterday -te now > /tmp/aureport.txt 2>&1

account=$(grep 'Number of changes to accounts, groups, or roles' /tmp/aureport.txt | awk '{print $NF}')
echo "修改账号,组,角色次数: $account"

teminal=$(grep 'Number of terminals' /tmp/aureport.txt | awk '{print $NF}')
echo "终端数: $teminal"

logins=$(grep 'Number of logins' /tmp/aureport.txt |awk '{print $NF}')
echo "登录次数:$logins" 

logins_fail=$(grep 'Number of failed logins' /tmp/aureport.txt |awk '{print $NF}')
echo "登录失败次数: $logins_fail"

login_user=$(grep 'Number of users' /tmp/aureport.txt | awk '{print $NF}')
echo "登录用户数: $login_user"

auth_num=$(grep 'Number of authentications' /tmp/aureport.txt | awk '{print $NF}')
echo "认证成功次数: $auth_num"

auth_fail=$(grep 'Number of failed authentications' /tmp/aureport.txt | awk '{print $NF}')
echo "认证失败次数: $auth_fail"

anomaly=$(grep 'Number of anomaly events' /tmp/aureport.txt | awk '{print $NF}')
echo "异常事件次数: $anomaly"

sys_call=$(grep 'Number of failed syscalls' /tmp/aureport.txt | awk '{print $NF}')
echo "系统调用失败次数: $sys_call"

crypto=$(grep 'Number of crypto events' /tmp/aureport.txt | awk '{print $NF}')
echo "加密事件次数: $crypto"

event=$(grep 'Number of events' /tmp/aureport.txt | awk '{print $NF}')
echo "事件数: $event"

echo ""
echo ""
/sbin/aureport --login --summary -i -if /var/log/audit/audit.log > /tmp/aureport.txt 2>&1
echo "登录用户及次数如下:"
cat /tmp/aureport.txt |grep -v audit.log