shell杂记1

Shell脚本
445
0
0
2022-04-11

变量

进程结束,变量被销毁

普通变量,子进程中是无法访问的,得是环境变量才行

作用域:当前脚本中得为全局变量,环境变量为超全局,函数内得为局部

export varname=value 声明并赋值一个环境变量

name=xqw 定义赋值一个普通变量 export name 再声明为环境变量

局部变量 local varname=val

位置变量 $1 $2 ... 引用脚本的参数

变量的命名:仅包含数字,字母,下划线,不能以数字开头;不能跟已有的环境变量重名

$? 上一个进程(执行的命令)的执行状态返回值

执行程序,有两种返回

结果

状态 $? 如果是正确被执行,则返回0, 如果是错误,则1~255(1,2,127系统保留)

脚本执行时,启动一个新bash

命令行直接执行的,相当于当前bash的子bash,会继承父进程的环境变量

系统自动执行的脚本,是需要设置环境变量的,因为执行时,并没有上层的父bash进程

unset varname 销毁变量

set

printenv

env

export

export PATH=$PATH:/bin/go

shell中变量的值默认是字符串,并不能直接算术运算

执行脚本

./xx.sh

xx.sh 要将路径加入到PATH中

bash xx.sh

source xx.sh

. xx.sh

判断表达式

[ expression ]

[[ expression ]]

test expression

-eq -ne -gt -ge -lt -le

[ $a -eq $b ]

echo $?

逻辑判断

&&

短路现象: a && b a为真,则执行后面的b , a为假,则b不用执行

id user3 &> /dev/null && echo 'user3 is exists.'

||

短路现象: a || b a为真,则后面的不用判断,a为假,则需要执行后面的

id root &> /dev/null || echo 'root not exists.' && echo 'root is exists.'

如果用户不存在,就添加用户?

id user2 &> /dev/null || useradd user2

! id user3 &> /dev/null && useradd user3

判断文件超过100行,就是大文件?

[ `wc -l ./passwd | cut -d' ' -f1` -gt 100 ] && echo 'big file.' || echo 'small file.'

id user1 && useradd user1 && echo 'user1' | passwd --stdin user1 || echo 'user1 exists.'

exit 退出当前进程脚本

exit 可以定义执行状态结果是什么;如果没有定义,则默认把exit前面那一条命令的退出执行状态当作整个脚本的执行状态结果

exit #

运算

let C=$A+$B

C=$[$A+$B]

C=$(($A+$B))

C=`expr $A + $B` expr命令 算术运算表达式 表达式中各操作数及运算符之间要有空格,而且要使用命令引用

文件测试

-e -f -d -r -w -x

[ -e file ]

[ -x file ]

脚本调试

bash -n xx.sh 检查语法,不执行脚本

bash -x xx.sh 单步,显示每一条执行的命令

注意:如果脚本中没有定义退出码,则最后执行的那一条命令的状态码,就是整个脚本的退出状态码

shift

执行其一次,$1 $2 $3 ... 位置变量的值整体向前移动一位

shift # 向前移动#位

特殊变量

$?

$1 $2

$# 参数个数

$* $@ 参数列表

练习

1. 传递三个参数给脚本,第一个为整数,第二个为算术运算符,第三个为整数,将计算结果显示出来,

要求保留两位精度,形如:./calc.sh 5 / 2

echo "scale=2;111/22" | bc

bc <<< "scale=2;111/22"

2. 传递3个参数给脚本,参数均为用户名,将此些用户的账号信息提取出来后,放置于 /tmp/testusers.txt文件中,并要求每一行行首有行号;

3. 判断当前主机的cpu生产商,其信息在/proc/cpuinfo文件中 vendor_id 一行中,

如果其生产商为AuthenticAMD,就显示其为AMD公司;

如果其生产商为GenuineIntel,就显示其为Intel公司;

否则,就说其为非主流公司;

cputype=`grep 'vendor_id' /proc/cpuinfo | head -1 | cut -d':' -f2 | sed -r 's@[[:space:]]+@@g'`

case $cputype in

AuthenticAMD)

echo "AMD.";;

GenuineIntel)

echo "intel.";;

*)

ehco "is not popular company.";;

esac

4. 给脚本传递三个整数,判断其中的最大数 和 最小数,并显示出来;

5. 写脚本,添加5个用户,user1~user5,每个用户的密码同用户名,用户添加完成后,显示用户成功添加

useradd user1 &> /dev/null && echo user1 | passwd --stdin user1 &> /dev/null && echo 'user1 add success.' || echo 'user1 exists.'

for i in {1..5}; doif id user$i &> /dev/null; then
echo "user$i exists."else
useradd user$i
echo "user$i" | passwd --stdin user$i &> /dev/null
echo "add user$i success."
fi
done

6. 添加3个用户,先判断其是否存在,不存在才添加,添加完成后,显示一共添加了几个用户,最后显示当前系统上共有多少个用户?

7. 给定一个用户,如果其uid为0,就显示为管理员,否则就显示其为普通用户

8. 删除某用户,一并删除其家目录,显示删除完成

9. 判断当前系统上是否有用户的默认shell为bash,如果有,就显示有多少个这类用户;否则,就显示没有这类用户;

10. 判断当前系统上是否有用户的默认shell为bash;如果有,就显示其中一个的用户名;否则,就显示没有这类用户;

11. 给定一个文件,判断这个文件中是否有空白行,如果有,则显示其空白行数,否则,显示没有空白行;

12. 给定一个用户,判断其UID与GID是否一样,如果一样,就显示此用户为“good guy”,否则,就显示此用户为“bad guy” , 进一步要求,不使用id命令获得其id

13. 传递两个参数,显示两者之积,之和?

14. 不使用id命令,判断用户是否存在,并且判断其uid,gid是否一样

USERNAME=user1

if ! grep "^$USERNAME\>" /etc/passwd &> /dev/null; then 
  echo "No such user: $USERNAME." 
  exit 1
fi
USERID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f3`
GROUPID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f4`
if [ $USERID -eq $GROUPID ]; then 
  echo "Good guy." 
  else 
  echo "Bad guy."
fi