shell是一种弱类型、解释型语言,不需要编译,只需要一个解释器,这里我们用bash。
输入如下命令:
more /etc/passwd
当前用户root登录的时候,默认打开的命令行用户接口就是bash,在这个bash中输入bash又会打开一个子bash接口,可以不断深入的嵌套bash,当然执行退出命令exit时,也会一层一层退出之前打开的bash。
环境变量 当前的shell和其子shell
export 名字=值
输入如下命令可以看到环境变量:
tail -n 5 /etc/profile
脚本在执行时都会启动一个子shell进程:
命令行中启动的脚本会继承当前shell环境变量。
系统自动启动脚本(非命令行启动):则需要自我定义环境变量。
本地变量 作用于当前bash
var_name=值
位置变量 用于 脚本执行的参数,$1 表示第一个参数,以此类推$1,$2….记录参数的位置
特殊变量 bash内置的用来保存某些特殊数据的变量。(也叫系统变量)
ls -l /usr
这时候显示结果:
现在我们要把这些命令的执行结果重定向到另一个地方,不在控制台显示:
命令执行正确的结果:
>覆盖重定向 覆盖原有内容
>> 追加重定向 在原有内容后追加
命令执行的错误结果:
2> 错误覆盖重定向
2>>错误追加重定向
&> 全部重定向 包括正确和错误的结果
这里要介绍一个shell编程中经常用到的重定向语句:
ls /usr &> /dev/null
null是一个设备文件,是一个字符输出设备:
这个字符输出设备有一个特点就是把数据重定向给他之后就再也找不回来了,相当于windows中的垃圾回收站,也叫数据黑洞。
查看变量:
set//可以查看当前bash下的所有变量
printenv//查看所有环境变量
${变量名},一般可以省略{},但不是所有情况都可以省略
自定义变量A=1
直接输出变量A的时候可以省略,但是当我们想输出变量再加一个字符串的时候,发现没有输出任何结果,原因是bash把Aa当成了一个变量,这个时候就需要{}来区分变量和常量字符串。
在bash中 通常有如下替换:
创建后缀为.sh的文件(没有后缀也可以)
第一行必须写:
#!/bin/bash //只能放第一行,称之为魔数
由于其起始的几个字节的内容是固定的(或是有意填充,或是本就如此)。根据这几个字节的内容就可以确定文件类型,因此这几个字节的内容被称为魔数 (magic number)
以下是脚本编写的练习:
写一个脚本,完成以下任务。
1、添加5个用户,user1,,,,user5
2、每个用户的密码同用户名,要求:添加密码完成后不显示passwd执行结果。
3、显示添加成功信息
1 #!/bin/bash
2 #
3 #
4 useradd $1 //添加用户 用户名为传入的第一个参数
5 echo $1 | passwd --stdin $1 &>/dev/null //使用passwd设置密码时,会有第二遍新密码提示输入,作为脚本,不可能等待用户输入,使用--stdin可以从标准输出例如echo,通过管道,提前拿到默认的密码,使其没有第二遍的提示,然后把密码设置成功的返回结果放入数据黑洞中
6 echo "Add User $1 success!" //打印提示信息
这个时候test.sh文件是没有执行权限的
chmod u+x test.sh//给脚本添加执行权限
./test.sh user//脚本执行的第一种方式
sh test.sh user1//执行的第二种方式
表达式只能返回真或假
条件表达式:
整数大小比较:
逻辑关系:在linux 中 命令执行状态 0 为真,其他为假
逻辑与: &&
第一个条件为假时,第二条件不用再判断,最终结果已经有;
第一个条件为真时,第二条件必须得判断;
逻辑或: ||
第一个条件为真时,第二条件不用再判断,最终结果已经有;
第一个条件为假时,第二条件必须得判断;
逻辑非: !
还是对上一个例子加一下逻辑判断
1 #!/bin/bash
2 [ ! $# -eq 1 ] && echo "args are error" && exit 5
3 id $1 &>/dev/null && echo "User $1 exit." && exit 2
4 id $1 &>/dev/null || useradd $1
5 id $1 &>/dev/null && echo "$1" | passwd --stdin $1 &>/dev/null && echo "Add User $1 success!"
第二行 使用了条件判断 $# 特殊变量 获得参数个数 如果不为1 打印提示信息 并 退出;
第三行 id $1 查看用户名为$1的用户信息 结果放入null中,若用户存在返回状态为0,逻辑判断为真,由于是逻辑与判断,仍然会执行后面的命令,打印用户已存在的提示,并退出,此时可以看出通过运用逻辑与的执行特性,替代完成了if else的判断逻辑即:用户存在,给提示,并退出,不存在,继续执行。
第四行代码使用了逻辑或命令,用户不存在 返回状态码非0,逻辑判断为假,对于逻辑或,当第一个判断为假的时候,仍要执行第二个逻辑判断,所以,会执行后面的添加用户操作。
第五行 使用逻辑与命令,当用户存在的时候 设置密码 并打印提示信息,用户添加完成
接着上面的要求,添加完成之后计算系统一共有多个用户。
1 #!/bin/bash
2 [ ! $# -eq 1 ] && echo "args are error" && exit 5
3 id $1 &>/dev/null && echo "User $1 exit." && exit 2
4 id $1 &>/dev/null || useradd $1
5 id $1 &>/dev/null && echo "$1" | passwd --stdin $1 &>/dev/null && echo "Add User $1 success!"
6 COUNT=`wc -l /etc/passwd | awk '{print $1}'`
7 echo "total Users are $COUNT"
第六行 定义一个变量 使用COUNT变量来定义用户总数,所有的命令要用反引号“括起来,使用awk切割字符串,得到用户数量
第七行 打印用户数量
If 条件 ;then
语句
elif 条件 ; then
语句
else
语句
fi
当then与if同行的时候 之间需要加分号;否则不需要加,最后结束条件判断要加fi 代表结束。
在if判断中的逻辑符号:
-a 与判断
-o 或判断
做如下例子,如果/etc/inittab文件的行数大于50,就显示好大的文件;
1 #!/bin/bash
2
3 C=`wc -l /etc/inittab | cut -d' ' -f1`
4 if [ $C -gt 50 ];then
5 echo "big file."
6 else
7 echo "small file."
8 fi
bash -n shell文件 :检查文件是否有语法错误。
bash –x shell 文件 :debug 执行文件
expr $A + $B
给定一个用户,获取其密码警告期限,然后判断用户密码使用期限是否已经小于警告期限,如果小于,则是显示“WARN” ,否则显示密码还有多少天到期。
1 #!/bin/bash
2
3 if [ ! $# -eq 1 ];then
4 echo "Args errors."
5 exit 3
6 fi
7
8 U_DAY=`grep $1 /etc/shadow | cut -d: -f3`
9 M_DAY=`grep $1 /etc/shadow | cut -d: -f5`
10 W_DAY=`grep $1 /etc/shadow | cut -d: -f6`
11 N_DAY=$[`date +%s`/86400]
12 USE_DAY=$[$N_DAY-$U_DAY]
13 L_DAY=$[$M_DAY-$USE_DAY]
14
15 if [ $L_DAY -le $W_DAY ];then
16 echo "warn"
17 else
18 echo "left day is $L_DAY"
19 fi
语法:
for 变量 in 列表 ; do
语句
done
获得列表:
实现这个例子:依次向/etc/passwd中的每个用户问好:hello 用户名,并显示用户的shell:
Hello ,root ,your shell :/bin/bash。
1 #!/bin/bash
2
3 C=`wc -l /etc/passwd | cut -d' ' -f1`
4 for I in `seq $C`;do
5 UN=`head -$I /etc/passwd | tail -1 | cut -d: -f1`
6 SH=`head -$I /etc/passwd | tail -1 | cut -d: -f1`
7 echo -e "hello, $UN \t Your shell: $SH"
8 done
计算100以内所有能被3整除的整数的和
1 #!/bin/bash
2
3 SUM=0
4 I=1
5 while true;do
6 if [ $I -gt 100 ];then
7 break
8 fi
9 if [ $[$I%3] -eq 0 ];then
10 SUM=$[$SUM+$I]
11 fi
12 I=$[$I+1]
13 done
14 echo "sum=$SUM"
传给脚本一个参数:目录,输出该目录中文件最大的,文件名和文件大小:
1 #!/bin/bash
2
3 if [ ! -d $1 ];then
4 echo "Args error"
5 exit 3
6 fi
7
8 C=`du -a $1 | wc -l`
9 for I in `seq $C`;do
10 FILE_SIZE=`du -a $1 | sort -rn | head -$I | tail -1 | awk '{print $1}'`
11 FILE_NAME=`du -a $1 | sort -rn | head -$I | tail -1 | awk '{print $2}'`
12 if [ -f $FILE_NAME ];then
13 KB=$[$FILE_SIZE/1024]
14 echo "${KB}KB , $FILE_NAME"
15 break;
16 fi
17 done