Shell-笔记


什么是 shell



脚本的创建过程

如果写出自己的第一个Shell脚本?

  1. 清理任务
  • 自然语言:步骤拆分,顺序化整理
  1. 编写可执行语句
  • 脚本语言:各步骤如何实现
  1. 完善脚本
  • 界面友好/结构规范/代码的优化
  • 代码简洁,执行效率高

如何运行Shell脚本

  1. 作为指定Shell解释程序的参数
  • sh path/fileName === bash test.sh
  • . path/fileName === source test.sh


2. 作为可独立运行的脚本程序

  • 为Shell脚本添加 x 权限,指定脚本路径即可执行

调试Shell脚本

  1. 直接观察执行过程
  • 执行中命令输出,报错信息
  • 与用户的交互
  1. 开启调试模式
  • sh -x 脚本文件
  1. 插入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