Shell-笔记
什么是 shell
脚本的创建过程
如果写出自己的第一个Shell脚本?
- 清理任务
- 自然语言:步骤拆分,顺序化整理
- 编写可执行语句
- 脚本语言:各步骤如何实现
- 完善脚本
- 界面友好/结构规范/代码的优化
- 代码简洁,执行效率高
如何运行Shell脚本
- 作为指定Shell解释程序的参数
- sh path/fileName === bash test.sh
- . path/fileName === source test.sh
2. 作为可独立运行的脚本程序
- 为Shell脚本添加 x 权限,指定脚本路径即可执行
调试Shell脚本
- 直接观察执行过程
- 执行中命令输出,报错信息
- 与用户的交互
- 开启调试模式
- sh -x 脚本文件
- 插入echo 断点
- echo '提示信息...'
#! /bin/bash
echo "1.创建名为 scapp 的用户账号";
# 如果用户已经存在会输出错误日志到 error.log
# 而不会出现到控制台
path="/home/logs";
file="error.log";
if [ ! -d log ]; then
mkdir -p $path && cd $path && touch $file;
fi
adduser scapp 2>> /home/logs/error.log
echo "2.初始化密码为 123456 ";
echo 123456 | passwd --stdin scapp &> /dev/null
免交互及输出处理
需要交互的可执行操作
- passwd改密码
- ssh远程登录
- vim文本编辑器
- 图形化的安装/配置过程
- ...
passwd 改名的免交互
- 选项 --stdin
- 从标准输入读取密码字串
- 可以从键盘,也可以由另一个命令给出
echo 123456 | passwd --stdin scapp &> /dev/null
忽略无关输出
- 黑洞设备 /dev/null
- 相当于只能写入,不能读出的单项文件
- 存放到其中数据都会丢失
- 用法: 可以执行语句 &> /dev/null
echo 123456 | passwd --stdin scapp &> /dev/null
只记录错误输出
- 根据需求,可以将出错的信息保存在指定文件
- 针对后台脚本的有效排错手段
- 适用于不便于交互但又需要查看报错的情况
- 用法: 可以执行语句 2> /path/file.log
# 如果用户已经存在会输出错误日志到 error.log adduser scapp 2>> /home/logs/error.log
命令组合方式
顺序分隔
- 使用分号
- 命令1;命令2;命令3
- 依次执行,只有先后,没有逻辑关系
x=134;y=456 mkdir -p /home/logs;cd /home/logs
- 典型应用
systemctl restart vsftpd; systemctl eable vsfpd
逻辑 "与" 分隔
- 使用 &&
- 命令1 && 命令2 && 命令3
- 逻辑关系为 '而且' (and),期待所有命令都能执行成功
- 一旦某个命令出现失败,后续命令不再执行
echo "hello" && echo "world"
hello
world
- 典型应用:
- 源代码编译安装软件,编译,编译过程
make && make install
逻辑 "或" 分隔
- 使用 ||
- 命令1 || 命令2 || 命令3
- 逻辑关系为 '或者' (or),任何一条命令成功都符合期望
- 只在前面的命令失败时,后续才会执行
echo "hello" || echo "world"
hello
- 典型应用
- 针对前置命令失败的情况下,这只补救任务
id scapp 2>/dev/null || (adduser scapp && id scapp)
组合逻辑分隔
- 命令1 && 命令2 || 命令3
- 当命令1执行成功时,会继续执行命令2,忽略命令3
- 当命令1执行失败时,会执行命令3,忽略命令2
# 判断用户是否存在 id scapp &> /dev/null && echo YES || echo NO # 判断CPU是否支持虚拟化 grep -qe 'vmx|svm' /proc/cpuinfo && echo YES || echo NO
管道操作
-
使用 |
-
将命令的屏幕输出交给另一端的命令处理
- 命令1 | 命令2 | 命令3
- 后续命令要能正常处理传来的 文本 ,否则无意义
-
典型应用
- 分屏浏览所有网络设备信息
- 将列出的信息交给less命令进行分页查看
ifconfig -a | less
- 应用实例
- 使用 find 在 /etc 目录下递归查找,列出所有普通文件(find 的结果是一行一行的)
- 将查找结果交给 wc 进行统计行数
find /etc -type f | wc -l
- 应用实例
- 统计正处于监听状态的TCP端口数
- 使用 netstat 命令列出所有的TCP连接数
- 将查找的结果交给 grep 过滤,计算状态为 LISTEN 的连接数
netstat -anpt | grep -c "LISTEN"
命令组合运用
标准输入输出,一切皆是文件。
一切皆是文件
- Unix/Linxu的基本思想
- 普通文件,目录,键盘,鼠标,... 都是以文件的形式存在
- 要访问硬件设备,必须找对应的设备文件
I/O 交互设备
- 标准输入设备 : 从此设备接受用户的输入的数据
- 标准输出设备 : 通过此设备向用户报告正常的命令输出结果
- 标准错误设备 : 通过此设备报给执行中的出错信息
| 类型 | 设备文件 | 文件描述号 | 默认设备 |
|---|---|---|---|
| 标准输入 | /dev/stdin | 0 | 键盘 |
| 标准输出 | /dev/stdout | 1 | 显示器 |
| 标准错误 | /dev/stderr | 2 | 显示器 |
stdout 与 stderr
- 运行成功(正常),其屏幕信息报给 stdout 设备
- 运行失败(异常),其屏幕信息报给 stderr 设备
重定向操作
什么是重定向?
- 重新指定命令执行时 I/O 设备的方向
- 不使用默认的键盘,显示器
- 改用指定文本文件
| 类型 | 操作符 | 用途 |
|---|---|---|
| 重定向输入 | < | 将文本输入来源键盘改为指定文件 |
| 重定向输出 | > | 将命令行的正常执行输出保存到文件,而不是直接显示在显示器 |
| 重定向输出 | >> | 与 > 类似,但操作是追加而不是覆盖 |
| 重定向错误 | 2> | 将命令行的执行出错信息保存到文件,而不是直接显示在显示器 |
| 重定向错误 | 2>> | 与 2> 类似,但操作是追加而不是覆盖 |
| 混合重定向 | &> | 相当于 >和 2>,覆盖到同一文件 |
| 混合重定向 | &>> | 2>&1 >> | 相当于 >>和 2>>,追加到同一文件 |
重定向输入
- 键盘输入 ---> 文件输入
- 比如,使用 mail 命令发电子邮件时
# 提前写好邮件内容 vim /root/mail.txt # 读取邮件发送 mail -s "A Test Mail" root@localhost < /root/mail.txt
重定向输出
- 输出到显示器 ---> 输出到文件
- 比如,需要保存某个命令输出的结果时
# 覆盖目标文件 echo 'search example.com' > /etc/resolv.conf # 追加到目标文件 echo 'nameserver 8.8.8.8' >> /etc/resolv.conf
重定向错误
- 输出到显示器 ---> 输出到文件
- 比如,需要保存某个命令输出的结果时
id scapp 2> /home/logs/error.log
混合重定向
- 将正常,错误输出分别/合并重定向
- 比如,需要区分命令输出,或者合并输出的信息时
# 分别记入不同文件 ls -ld /rootx /root > /root/ls.log 2> /root/err.log # 同时追加记入一个文件 # 2>&1 把错误信息合并到标准输出 在追加或是覆盖文件 ls -ld /rootx /root &>> /root/info.log ls -ld /rootx /root >> /root/info.log 2>&1 ls -ld /rootx /root 2>&1 >> /root/info.log