shell脚本
shell是Linux内核与用户之间的解释器程序
通常指 /bin/bash
bash是shell脚本语言的一个具体实现,shell是所有解释器的概念统称,而bash则是解释器的一个具体实现;常用的解释器有
1. [root@svr5 ~]# cat /etc/shells
2. /bin/sh
3. /bin/bash
4. /sbin/nologin
5. /bin/tcsh
6. /bin/csh
7. /bin/ksh
切换用户的shell环境
1. [root@svr5 ~]# ksh //进入ksh环境
2. [root@svr5]~# exit //返回到切换前的bash环境
若希望修改用户的登录Shell,管理员可以直接通过usermod命令设置。比如,以下操作可将用户zhangsan的登录Shell改为/bin/ksh:
1. [root@svr5 ~]# usermod -s /bin/ksh zhangsan //执行修改操作
2. [root@svr5 ~]# grep 'zhangsan' /etc/passwd
3. zhangsan:x:516:516::/home/zhangsan:/bin/ksh //修改后
tab键,依赖于bash-completion包,使用tab键需要安装bash-completion包
history历史命令
- 检查历史命令的容量。
默认记录1000条,通过全局变量HISTSIZE设置,对所有用户有效
1. [root@svr5 ~]# grep HISTSIZE /etc/profile
2. HISTSIZE=1000
- 查看以为当前用户记录的命令条数:
1. [root@svr5 ~]# history | wc -l
- 调用指定的历史命令。
重新执行最近一次以cat开头的历史命令操作:
[root@svr5 ~]# !cat
- 清空历史命令记录
1. [root@svr5 ~]# history -c //清空自己的历史命令
2. [root@svr5 ~]# > ~/.bash_history //清空记录文件
3. [root@svr5 ~]# history //再次检查历史命令列表
4. 42 > ~/.bash_history
5. 43 history
alias自定义别名
- 查看已经定义的别名列表。
1. [root@svr5 ~]# alias
2. alias cp='cp -i'
3. alias l.='ls -d .* --color=tty'
4. alias ll='ls -l --color=tty'
5. alias ls='ls --color=tty'
6. alias mv='mv -i'
7. alias rm='rm -i'
8. alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
别名设置一般存放在用户的.bashrc文件内:
[root@room8pc205 ~]# grep '^alias' .bashrc
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias zh='convmv -r -f GB2312 -t utf8 --notest'
- 自定义新的别名
[root@will 桌面]# alias will='ls -lh'
[root@will 桌面]# alias
...
alias will='ls -lh'
alias zh='convmv -r -f GB2312 -t utf8 --notest'
[root@will 桌面]# will /etc/hostname
-rw-r--r--. 1 root root 5 8月 7 18:47 /etc/hostname
- 取消别名
取消单个别名
[root@will 桌面]# unalias will
[root@will 桌面]# will /etc/hostname
bash: will: 未找到命令...
重定向标准输入/输出/错误输出
标准输入(stdin),描述号为0;标准输出(stdout),描述号为1;标准错误(stderr),描述号为2.
- 重定向标准输出。使用大于号(>)将命令的正常输出重定向到文件:
1. [root@svr5 ~]# ls -ld /etc/ //正常应输出到屏幕
2. drwxr-xr-x. 140 root root 8192 8月 2 04:45 /etc/
3. [root@svr5 ~]# ls -ld /etc/ > stdout.txt //重定向到文件
4. [root@svr5 ~]# cat stdout.txt //确认重定向输出的结果
5. drwxr-xr-x. 140 root root 8192 8月 2 04:45 /etc/
重定向>操作会覆盖目标文件(先清空,再输入):
改用 >> 可实现追加重定向输出:
2. 重定向标准错误。
对于命令执行出错的信息,使用>无法保存,仍然会输出到屏幕。比如,可使用ls命令同时查看两个对象(其中abc.txt不存在)重定向输出:
[root@will ~]# ls -l abc.txt /etc/fstab > sdterr.txt
ls: 无法访问abc.txt: 没有那个文件或目录
[root@will ~]# cat sdterr.txt
-rw-r--r--. 1 root root 790 8月 7 18:47 /etc/fstab
//最终正确的结果重定向到文件中,错误的直接输出在屏幕
使用2>可重定向错误信息,比如,同上的命令:
[root@will ~]# ls -l abc.txt /etc/fstab 2> sdterr.txt
-rw-r--r--. 1 root root 790 8月 7 18:47 /etc/fstab
[root@will ~]# cat sdterr.txt
ls: 无法访问abc.txt: 没有那个文件或目录
可以两者结合使用,将错误日志和正确日志分别存放在不同的文件中:
[root@will ~]# ls -l abc.txt /etc/fstab 2> sdterr.txt > stdin.txt
[root@will ~]# cat stdin.txt
-rw-r--r--. 1 root root 790 8月 7 18:47 /etc/fstab
[root@will ~]# cat sdterr.txt
ls: 无法访问abc.txt: 没有那个文件或目录
类似的,2>>可实现追加重定向错误结果;
[root@will ~]# ls myfile 2>sdterr.txt
[root@will ~]# ls abc.txt 2>> sdterr.txt
[root@will ~]# cat sdterr.txt
ls: 无法访问myfile: 没有那个文件或目录
ls: 无法访问abc.txt: 没有那个文件或目录
若希望将整场输出,错误输出重定向到同一个文件,可使用&>:
[root@will ~]# ls -l abc.txt /etc/fstab &> sdtout.txt
[root@will ~]# cat sdtout.txt
ls: 无法访问abc.txt: 没有那个文件或目录
-rw-r--r--. 1 root root 790 8月 7 18:47 /etc/fstab
- 重定向标准输入
重定向输入是在非交互脚本中将事先编写好的文件内容输入到脚本中;比如发邮件时,事先将邮件内容编写在toUser1.mail中,在脚本中使用重定向输入将邮件内容读取。
mail -s user1 root < toUser1.mail
- 管道操作
借助于管道符“|”,可以将前一条命令的结果的标准输出交给另一条命令,在一条命令行内可依次使用多个管道。
- 统计/etc/目录下资料的数量
[root@will ~]# ls /etc/ |wc -l
289
- 列出yum库中名称包含cluster的软件包。
[root@will ~]# yum list | grep cluster
lvm2-cluster.x86_64 7:2.02.130-5.el7 dvd
pacemaker-cluster-libs.x86_64 1.1.13-10.el7 dvd
- 统计yum仓库中名称包含luster的软件包的个数。
[root@will ~]# yum list | grep clusteryum list | grep cluster | wc -l
2
Shell脚本
一个规范的Shell脚本构成包括:
脚本名 *.sh
- 脚本声明 (需要的解释器、作者信息等)
- 注释信息(步骤、思路、用途、变量含义等)
- #autor:作者联系方式
- #version: 版本
- #Description:简介
- 可执行语句(操作代码)
- 执行脚本的方式:
- bash/sh/ksh/等解释器 +文件路径/文件名(该方法不需要文件有执行权限);
- 直接执行文件绝对路径(需要执行权限)
- 当前如果已经在文件所在目录下时,可用./abc.sh执行
- source /abc.sh (不开启子进程)
#!/bin/bash
echo "please input userName:"
read userName
date >> user.log
echo "错误日志:" >> user.log
for i in {1..10}
do
useradd ${userName}$i 2>> user.log
echo "123" | passwd --stdin ${userName}$i >/dev/null
done
其中#!/bin/bash 是脚本的解释器,后边跟内容。
*删除时需注意 rm -rf /etc/yum.repos.d/ 删除文件夹下的东西时必须加“*”,不加星号则会把文件夹目录删除 **
Shell变量
- 变量的定义/赋值/查看
- 新建变量并赋值:
[root@will ~]# test=290
- 查看变量:echo $变量名 或者:echo ${变量名}
[root@will ~]# echo ${test}RMB
290RMB
- 撤销自定义的变量
[root@will ~]# unset test
[root@will ~]# echo $test
//变量已空
使用环境变量
- 查看环境变
全局文件为/etc /profile,对所有用户有效;用户文件为~/.bash_profile,仅对指定用户有效。
查看/etc/rpofile文件内容:
1. [root@svr5 ~]# cat /etc/profile
2. .. ..
3. HOSTNAME=`/bin/hostname`
4. HISTSIZE=1000
5. .. ..
6. export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC
7. .. ..
- 使用环境变量
当前用户的变量USER记录了用户名、LOGNAME记录了登录名、HOME记录了宿主目录、SHELL记录了登录shell、HOSTNAME记录主机名、TERM记录登录终端类型:
[root@will ~]# echo $TERM
xterm-256color
[root@will ~]# echo $HOSTNAME
will
[root@will ~]# echo $USER
root
[root@will ~]# echo $LOGNAME
root
[root@will ~]# echo $SHELL
/bin/bash
环境变量PS1表示Shell环境的一级提示符,即命令提示符[root@will ~]# (\u 用户名、\h 主机名、\W 工作目录、$ 权限标识)
[root@will4_7 ~]# echo $PS1
[\u@\h \W]\$
修改一级命令提示符:
[root@will4_7 ~]# PS1='saniu#'
saniu#PS1='saniu# '
saniu# ls /
环境变量PS2表示二级提示符,出现在强制换行、at任务编辑等场合:
[root@will ~]# ls \
> //此处为二级提示符
修改二级提示符方法同上。
3. 查看系统变量
使用env命令可查看所有环境变量:
1. [root@svr5 src]# env
2. HOSTNAME=svr5.tarena.com
3. SHELL=/bin/bash
4. HISTSIZE=1000
5. SSH_CLIENT=192.168.4.110 59026 22
6. OLDPWD=/root
7. SSH_TTY=/dev/pts/0
8. USER=root
9. .. ..
使用set可查看所有变量(包括env能看到的环境变量)
[root@will ~]# set |wc -l
2177
- 使用位置变量与预定义变量
[root@will ~]# cat test01.sh
#!/bin/bash
1. echo $0 //脚本的名称
2. echo $1 //第一个参数
3. echo $2 //第二个参数
4. echo $* //所有参数
5. echo $# //所有的综合
6. echo $$ //当前进程的进程号
7. echo $? //上一个程序的返回状态码
[root@will ~]# bash test01.sh a b c hh tt
test01.sh
a
b
c
a b c hh tt
5
8559
0
变量$?结合if语句在编写脚本时可以经常使用,如果上条命令执行正确,则该变量值为0,错误则为非0
变量的扩展应用
三种引号对变量赋值的影响
- 双引号的应用
使用双引号可以界定一个完整的字符串(空格的个数不会缩减)
[root@will ~]# school=shang hai di er gong ye da xue
bash: hai: 未找到命令...
[root@will ~]# echo $school
//此处是空值
[root@will ~]# school="shang hai di er gong ye da xue"
[root@will ~]# echo $school
shang hai di er gong ye da xue
- 单引号的应用
界定一个完整的字符串,并且可以实现屏蔽特殊符号的功能。
[root@will ~]# echo "$school"
shang hai di er gong ye da xue
[root@will ~]# echo '$school'
$school
- 反撇号``或()的应用使用反撇号或()的应用 使用反撇号或()的应用使用反撇号或()时,可以将命令执行的标准输出作为字符串存储,因此简称为命令替换符。
[root@will ~]# tar -czf log-`date +%Y%m%d`.tar.gz /var/log
tar: 从成员名中删除开头的“/”
[root@will ~]# ls
log-20190808.tar.gz
... ...
使用read命令从键盘读取变量值
- read的基本用法
执行后会等待并接受用户输入(无任何提示的情况),并赋值给str:
[root@will ~]# read str
nihao
[root@will ~]# echo $str
nihao
结合参数-p输出提示信息
[root@will ~]# read -p "请输入一个整数:" i
请输入一个整数:234
[root@will ~]# echo $i
234
- stty终端显示控制
将回显功能关闭(stty -echo),
将回显功能恢复(stty echo),
创建一个测试脚本:
#!/bin/bash
read -p "请输入用户名:" userName
stty -echo
read -p "请输入密码:" password
stty echo
echo ""
echo "用户名:$userName 密码:$password"
测试结果:
[root@will ~]# bash sttytest.sh
请输入用户名:zhangsan
请输入密码:
用户名:zhangsan 密码:123456
使用export发布全局变量
- 默认情况下,自定义的变量为局部变量,只在当前shell环境中有效,而在子Shell环境中无法直接使用。比如已定义的school变量,当进入到sh或bash子shell后,变量school将处于未定义状态;
- 若希望定义的变量能被子进程使用,可以使用export命令将其发布为全局变量。使用export发布时,只需要指定变量名(可以有多个)即可,也可以通过export命令直接设置新的全局变量:
[root@will /]# echo $school
shang hai di er gong ye da xue
[root@will /]# bash
[root@will /]# echo $school
[root@will /]# exit
exit //退回到原环境中
[root@will /]# export school
[root@will /]# bash
[root@will /]# echo $school
shang hai di er gong ye da xue