文章目录
shell相关基础知识
脚本的自动化注释
- 编辑/etc/vimrc,加入如下内容:
脚本的调式
使用sh 的 "-x"选项可用来跟踪脚本的执行,是调试shell脚本的强有力工具。“-x”选项使shell在执行脚本的过程中把它实际执行的每一个命令行显示出来,并且在行首显示一个"+"号。 "+"号后面显示的是经过了变量替换之后的命令行的内容,有助于分析实际执行的是什么命令。 “-x”选项使用起来简单方便,可以轻松对付大多数的shell调试任务,应把其当作首选的调试手段。
sh -x file.sh
例如:我们可以利用sh -x 调试之前的清空日志的脚本
[root@server mnt]# sh -x clear_log.sh
+ test root == root
++ sed -n '$=' /etc/rsyslog.conf
+ Max_Lines=91
++ sed '/^:/d;s/-//g'
++ grep RULES /etc/rsyslog.conf -A 91
++ awk '!/^$/&&!/^#/{print $2}'
+ TARGET_LOG='/var/log/messages
/var/log/secure
/var/log/maillog
/var/log/cron
/var/log/spooler
/var/log/boot.log'
+ echo /var/log/messages /var/log/secure /var/log/maillog /var/log/cron /var/log/spooler /var/log/boot.log
/var/log/messages /var/log/secure /var/log/maillog /var/log/cron /var/log/spooler /var/log/boot.log
+ for LOG_FILE in '$TARGET_LOG'
+ echo -e '\033[32m/var/log/messages is clear!!\033[0m'
/var/log/messages is clear!!
+ for LOG_FILE in '$TARGET_LOG'
+ echo -e '\033[32m/var/log/secure is clear!!\033[0m'
/var/log/secure is clear!!
+ for LOG_FILE in '$TARGET_LOG'
+ echo -e '\033[32m/var/log/maillog is clear!!\033[0m'
/var/log/maillog is clear!!
+ for LOG_FILE in '$TARGET_LOG'
+ echo -e '\033[32m/var/log/cron is clear!!\033[0m'
/var/log/cron is clear!!
+ for LOG_FILE in '$TARGET_LOG'
+ echo -e '\033[32m/var/log/spooler is clear!!\033[0m'
/var/log/spooler is clear!!
+ for LOG_FILE in '$TARGET_LOG'
+ echo -e '\033[32m/var/log/boot.log is clear!!\033[0m'
/var/log/boot.log is clear!!
shell 脚本的执行
sh 的方式执行脚本
sh执行脚本的方法是相当于用sh的方式开了一个shell执行。
- 具体例子:我们先写一个可以长期运行的脚本,使用sh 执行脚本后,切换至后台,使用
ps f
显示树状结构,表达进程间的相互关系。
对脚本加执行权限,直接执行
加了执行权限后chmod +x
,读取文件里的默认的shell进行执行,相当于再开一个指定的shell(一般脚本文件中会写,例如#!/bin/bash),一般用绝对路径执行。
- 同样的例子,进行测试
source的方式执行脚本
source方法执行脚本是直接在当前shell里执行。
注意:使用符号. 加脚本也是在当前shell中执行脚本,例如:. source.sh
- 例子:
一道经典面试题
如何在当前shell中生效显示出脚本中变量的值?
- 举个例子:在脚本中写入
A=10
,分别使用几种执行脚本的方法执行。
所以,使用source的方法执行即可使脚本中的变量值赋予当前的shell环境下。
shell中的变量
变量的定义
变量即在程序运行过程中它的值是允许改变的量;
变量是用一串固定的字符来标示不固定的值的一种方法;
变量是一种使用方便的占位符,用于引用计算机内存地址,该地址可以存储 Script 运行时可更改的程序信息;
在 shell 中变量是不能永久保存在系统中的,必须在文件中声明。
## 在 shell 脚本中变量的种类
在 shell 中变量分为环境级变量,用户级变量,系统级变量。
环境级变量
环境级变量只在当前 shell 中生效,shell 关闭变量丢失。
export A=1
用户级变量
用户级变量写在用户的骨文件中/etc/skel/,ls -a /etc/skel
只针对当前用户生效
[root@server ~]# ls -a /etc/skel/
. .. .bash_logout .bash_profile .bashrc .config .mozilla
也可以在用户家目录查看:
文件 | 作用 |
---|---|
.bash_profile | 用户级:修改用户的环境变量 |
.bashrc | 修改此shell的环境设定,生效后每次进入到这个shell都会 |
.bash_history | 此用户的shell上的历史记录 |
.bash_logout | 此用户退出时的操作 |
实验:
在.bash_profile中写入变量值 export A=1
在这个用户下都是受用的,可以退出后重进,发现成功 。但是用-切换到其他用户,是既切换用户身份,又切换环境,因为这个只针对于当前用户的环境,所以不显示。如果用su不切换环境就可以。
系统级变量
系统级变量被写在系统的配置文件 /etc/profile 或者 /etc/profile.d/ 中,对于所有用户都生效。
就相当于为每个用户指定了变量,但是变量是先读系统级在读用户级(如果有的话),所以最后显示的是用户级的。
- 示例:我们先清除之前设置的用户级变量,然后在/etc/profile 写入 export A=99,退出shell后重新进入,发现A=99,我们在此基础上,在.bash_profile写入export A=".bash_profile",再次退出登录,发现A=.bash_profile,也就说明了读取顺序。
字符的转译及变量的声明
参数 | 含义 |
---|---|
\ | 转译单个字符 |
" " | 弱引用,批量转译 " " 中出现的字符, |
’ ’ | 强引用,批量转译 ’ ’ 中出现的字符 |
’ ’ 与 " " 两者的区别 | " " 不能转译 “”,"`","!","$" |
${} | 变量声明(精确声明具体变量) |
示例:
[westos@server ~]$ A=1
[westos@server ~]$ echo $AB ##没有声明AB这个变量
[westos@server ~]$ echo ${A}B ##使用{}精确是A这个变量
1B
变量的值传递
参数 | 含义 |
---|---|
$1 | 脚本后的第一串字符串 |
$2 | 脚本后的第二串字符串 |
$# | 脚本后所跟字符串的个数 |
$* | 脚本后跟的所有字符串,模式为“ 1 2 3 ” |
$@ | 脚本后跟的所有字符串,模式为“ 1”“2”“3” |
$$ | 当前运行的shell的PID |
示例:
面试题:关于$*和$@的区别:
- 总结:根据上面的实验结果,$*是一次输出,将脚本后所有的字符串整合成一个字符串;$@是分次输出,将脚本后的字符串按照空格分段输出的字符串。
带交互式的变量:read
read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量。
常用参数 | 含义 |
---|---|
-p | 后面跟提示信息,即在输入前打印提示信息。 |
-s | 安静模式,在输入字符时不再屏幕上显示,例如login时输入密码。 |
-n | 后跟一个数字,定义输入文本的长度,很实用。 |
- 示例:写一个交互式脚本,输入ip,输出是否通:
测试:
命令别名的设定alias
语 法:alias 别名=‘指令名称’ ,unalias 别名 (删除别名)
参 数:若不加任何参数,则列出目前所有的别名设置。
- 临时设定别名:alias xie = ‘vim’
- 当前shell环境下永久:
vim ~/.bashrc
写入别名,使用source生效(或者重新进入shell),但是切换到别的用户就不能用了
- shell下所有用户:/etc/bashrc 写入别名, 所有方法切换都生效。因为su 和su - 都会读取这个文件,所以会生效。如果是写入到/etc/profile ,只有su - student 切换是alias才会生效。
利用命令执行结果设定变量
在bash中,$( )与` `(反引号)都是用来作命令替换的。
命令替换与变量替换差不多,都是用来重组命令行的,先完成引号里的命令行,然后将其结果替换出来,再重组成新的命令行。
- 区别:在操作上,这两者都是达到相应的效果,但是建议使用$( ),理由如下:
``很容易与’ '搞混乱,尤其对初学者来说,而$( )比较直观。
最后,$( )的弊端是,并不是所有的类unix系统都支持这种方式,但反引号是肯定支持的。
命令退出值
$? 是命令在执行完成之后产生的退出值,范围是 [0-255]。
当 $0=0 时标示命令执行没有错误输出。(可以用作判断命令是否执行成功的条件)
这个退出值可以用 exit 命令执行 ,例如 exit 66,此时echo $? 结果就是66。
脚本中的函数
脚本中的函数时把一个复杂的语句块定义成一个字符串的方法。
实际问题
- Q:用函数的方法写一个脚本进行用户控制,使用交互式输入,分别实现创建用户、删除用户、退出选项。
- A:思路:将功能模块化,函数之间通过调用将功能连接到一起。
#!/bin/bash
echo -e "[C]reate [D]elete [E]xit\n"
Choose_Function(){
read -p "Please input options:" Option
test "$Option" == "C" -o "$Option" == "Create" -o "$Option" == "create" &&{
Create_Func
Choose_Function
}
test "$Option" == "D" -o "$Option" == "Delete" -o "$Option" == "delete" &&{
Delete_Func
Choose_Function
}
test "$Option" == "E" -o "$Option" == "Exit" -o "$Option" == "exit" &&{
echo "bye!"
exit
}||{
echo -e "\033[31m$Option is wrong option!\033[0m"
Choose_Function
}
}
Create_Func(){
read -p "Please input username:" Username
id $Username &> /dev/null
test "$?" == "0" &&{
echo -e "\033[31m$Username is exist!\033[0m"
}||{
useradd $Username
read -p "Please input passwd:" -s Passwd
echo $Passwd | passwd --stdin $Username &> /dev/null
echo -e "\033[32m$Username is created !!\033[0m"
}
}
Delete_Func(){
read -p "Please input username:" Username
id $Username &> /dev/null
test "$?" == "0" &&{
userdel -r $Username &> /dev/null
echo -e "\033[32m$Username is deleted!!\033[0m"
}||{
echo -e "\033[31m$Username is not exist!!!\033[0m"
}
}
Choose_Function
效果: