地地道道的

1.1 执行脚本

./xxx.sh --要求有执行权限,并且一定要声明shell类型(#!/bin/bash或都#!/bin/sh)

sh xxx.shbash xxx.sh --不需要有执行权限,也可以不声明shell类型

sh -x xxx.sh --可以显示执行过程,帮助排错


1.2 环境变量

利用export把自定义变量转化为环境变量

# a=1
# bash      --进入到子bash
# echo $a   --子bash里看不到此变量值

# exit      --退到父bash
exit
# export a=1 --使用export命令转化为环境变量
# bash
# echo $a   
1           --再在子bash里可以看到此变量值
# 第1个脚本
# cat 1.sh 
#!/bin/bash

export aaa=111 --第一个脚本的变量加export,才能在第二脚本里调用
sh 2.sh

# 第2个脚本
# cat 2.sh 
#!/bin/bash

echo $aaa

# 执行脚本
# sh 1.sh 
111

1.3 变量定义

1,区分大小写,同名称但大小写不同的变量名是不同的变量

# a=2
# A=3

# echo $a
2
# echo $A
3

2,定义时的格式要注意,等号两边不能有空格,对于有空格的字符串做为赋值时,要用引号引起来

B="hello world"
B='hello world haha'    
--单引号和双引号在这里都可以,后赋值的会覆盖前面的赋值
--在脚本里注意引号的相互嵌套,要成对出现

3,单引号与双引号的区别,单引号内的变量或者特殊字符仅为一般字符,但双引号内的变量或者特殊字符可以保持它的变量特性

# echo '$B'
$B

# echo "$B"
hello world haha

4,变量名可以是字母或数字或下划线,但是不能以数字开头

# c123=aaa
# echo $c123
aaa

# 123c=aaa
bash: 123c=aaa: command not found

# _abc11122=3   --可以以下划线开头
# echo $_abc11122
3

5,变量赋值可以有多个

例如 echo $PATH ,以":"分隔(这里准确来说还是一个值)

6,变量的获取方式:$变量名 , ${变量名}

# echo $a
3
# echo ${a}
3

# echo ${a:1:2} --切片的方式:1表示从第二个开始,2表示截2个字符
23
# echo ${a:2:2}
34

7,取消变量的命令:unset 变量名

# unset a
# echo $a
#

8,别的变量定义方式

# rpm -qf `which mount`
# ls /lib/modules/`uname -r`/   --执行符号的使用,执行符号是tab键上面的那个符号
# scp /root/Desktop/eicar.com 2.2.2.36:`pwd`

# a=`which mount`       --这样定义
# echo $a
/bin/mount

# a=$(uname -r)
# echo $a
2.6.18-164.el5

9,使用read做交互式变量定义

# read -p "输入你的名字:" name
输入你的名字:张三

# echo $name
张三

1.4 六种符号

下面六种符号的作用:
$() $(()) $[] ${} ` ` [[ ]] 

$() 等同于 执行符号  ` `,但是如果要嵌套使用,使用` `符号就不行,要用$()
但如果不是嵌套的使用` `是可以的,如a="`which mount` `which yum`"

$(())  等同于  $[]  --这两个是运算符号
[[ ]]  这是在比较条件里做匹配的写法
# a=$(rpm -qf `which mount`)
# echo $a
util-linux-2.13-0.52.el5

# a=$(rpm -ql $(rpm -qf `which mount`) |grep /bin/mount)
# echo $a
/bin/mount

# 求现在到1970年相隔多少天
# echo $[`date +%s`/86400]
# echo $(($(date +%s)/86400))

1.5重定向符

# mail -s "11111" root < /etc/fstab

# ping -c 1  10.1.1.1  &> /dev/null
# ping -c 1  10.1.1.1  >& /dev/null
# ping -c 1  10.1.1.1  > /dev/null 2>&1  --这三条都是把标准输出和错误输出都扔到/dev/null设备
# cat passwdfile  --一个存放密码的文件,里面密码123,写两次
123
123

# passwd user1 < passwdfile > /dev/null 2>&1
--可以修改密码,并且把正确或错误信息都扔给了黑洞设备

# ssh 10.1.1.110 < passwd
Pseudo-terminal will not be allocated because stdin is not a terminal.
[email protected]'s password: 
--ssh是不可以的,需要用到expect脚本

1.6 EOF符号

#注意下面这两种区别
cat > /tmp/abc <<EOF
你好
EOF

cat >> /tmp/abc <<EOF
哈哈
EOF
# 自动配置本地yum的配置文件 
# cat > /etc/yum.repos.d/rhel-source.repo <<EOF
[server]
name=server
baseurl=file:///yum/Server
enabled=1
gpgcheck=0
[loadbalancer]
name=loadbalancer
baseurl=file:///yum/LoadBalancer
enabled=1
gpgcheck=0
[HighAvailability]
name=HighAvailability
baseurl=file:///yum/HighAvailability
enabled=1
gpgcheck=0
EOF

1.7 特殊变量

echo $0     #代表脚本本身名
echo $1     #代表脚本运行时接的第一个参数
echo $2     #代表脚本运行时接的第二个参数
echo $3     #代表脚本运行时接的第三个参数

echo $$     #本shell程序运行的PID

echo $*     #代表所有参数
echo $@     #也是代表所有参数

echo $#     #显示后面接的参数的个数

echo $?     #上一条命令执行成功则返回0;上一条命令失败则返回非0

1.8 实践示例

1.8.1 实践示例1

写一个脚本,每天凌晨0点01分mv /var/log/aaa.log,备份到/backup/年/月/年-月-日期.aaa.log,然后再touch /var/log/aaa.log,每次日志轮转后,都在/var/log/message里记录一条日志已经轮转的信息,并且发一个通知邮件给user1用户,要求把年,月,日用变量的定义。最后把这个脚本然后放到crontab里去执行(有兴趣课后可以在此基本上再加一条需求:日志只保留两年以内的,两年以前的都删除)
--如果是每天的晚上23点59分做,又应该如何改,要注意哪些情况?

问题:假设一个服务的日志为/var/log/aaa.log,做了mv操作后(假设mv成bbb.log),再touch一个新的aaa.log,请问,服务要写的新的日志会记录到新touch的aaa.log里吗?
答案:不会,还会写到mv的那个bbb.log里(因为程序通过innode去写,同一分区mv文件innode不变)。所以要在mv后通知程序(重启服务或者kill -HUP或者kill -USR1(apache,nginx可以用USR1信号))

#!/bin/bash

year=`date -d "-1 days" +%Y`
month=`date -d "-1 days" +%m`
day=`date -d "-1 days" +%d`

mkdir /backup/$year/$month/ -p

mv /var/log/aaa.log /backup/$year/$month/$year-$month-$day.aaa.log
touch /var/log/aaa.log
kill -HUP `cat /var/run/xxx.pid` # 冬瓜:没看懂
echo "succeed" | mail -s "$year-$month-$day log rotated"  user1 # 冬瓜:没看懂
logger -t "日志轮转" "成功了@-@" # 冬瓜:没看懂

1 0 * * * sh /xxx/xxx.sh
59 23 * * * sh /xxx/xxx.sh

如果要每两天轮转一次
1 0 */2 * * sh /xxx/xxx.sh

1.8.2 实践示例2

写一个脚本,方便你以后自己查找笔记,比如:要查找关键字samba,则输入samba,就自动帮你显示出来,并将此脚本放入$PATH路径中,然后给执行权限,以后可以当成命令来使用(提示,grep samba * )

#!/bin/bash

read -p "输入你要查找笔记的分类(basic|shell|mysql|program|arch|oracle):" dir

cd /share/20170331/$dir

read -p "输入你要查找笔记的关键字:" keyword

gedit `grep $keyword * |cut -d":" -f1 |sort |grep -v ~$ |uniq -c |sort -n |tail -1 |awk '{print $2}'`

1.8.3 实践示例3

实现一个普通用户登出时,显示登录了多久;如abc用户登出时,会自动显示"你好,abc,你一共登录了xx时xx分xx秒,bye bye"

提示: 两个变量的相减运算$[$a-$b]

# vim /home/abc/.bash_profile 
logintime=`date +%s`

# vim /home/abc/.bash_logout
clear
logouttime=`date +%s`
alltime=$[$logouttime-$logintime]
hours=$[$alltime/3600]
minutes=$[$alltime%3600/60]
seconds=$[$alltime%60]
echo "你好,$USER,你一登录$hours时$minutes分$seconds>秒,bye bye"

扩展:如何把这个实现到所有的用户都实现这个功能
第一种,把上面写成shell脚本循环执行
第二种,先说一下useradd abc这条命令到处执行了哪些步骤

useradd创建用户的7个步骤

步骤1:/etc/passwd加上abc:x:532:533::/home/abc:/bin/bash
步骤2:/etc/shadow加上abc:!!:14709:0:99999:7:::  --密码可以用grub-md5-crypt 命令建立
步骤3:/etc/group加上abc:!!:14709:0:99999:7:::
步骤4:/etc/gshadow加上abc:!::
步骤5:mkdir /home/abc     --建立家目录,手动建立后注意属主和属组
步骤6:touch /var/spool/mail/abc   --建立用户的存放邮件的文件  手动建立后注意属主和属组
步骤7:cp /etc/skel/.bash* /home/abc/  --拷环境变量模版到用户家目录

通过讲了useradd abc的步骤,第二种方法就可以想到了,就是把上面的做法写到/etc/skel/.bash_profile和/etc/skel/.bash_logout里。然后建立任何用户都会拷贝这些已经修改好的。但这种方法比较适合用户都还没有建立的情况,第一方法就无所谓。

猜你喜欢

转载自www.cnblogs.com/zhangsonghui/p/8975213.html
今日推荐