YOLO813

Linux控制脚本的初步学习与帮助文档的了解

    与本文无关的前言:服务器的防火墙策略还是要慎重,之前一直使用firewalld,这次学习了下iptables,一行代码直接把自己踢出了ssh远程连接。

iptables -P INPUT DROP

iptables命令即时生效,还好重启服务器可以重置策略,否则又得重新安装一遍Linux了。

 

    正文:Linux的脚本没有想象的那么复杂,今天就来练手一下Linux下的for、while、case三种控制流语句,学会了控制流程,基本就可以写一些像模像样的Linux脚本了。三种语句具体的含义和语法就不废话了,直接上测试代码。

    利用for语句批量添加Linux用户。

    首先新建一个user.txt,里面我写了4个名字,其中xiaofei这个用户已经存在于/etc/passwd

而我要做的就是创建不存在的用户名,代码如下(由于是测试代码就不写注释了):

#!/bin/bash
USERNAMES=`cat /opt/test1/user.txt`
read -p "input password: " pwd
for USER in $USERNAMES
do
        id $USER &> /dev/null
        if [ $? -eq 0 ]
        then
                echo "User $USER is already exists!"
        else
                useradd $USER &> /dev/null
                echo $pwd | passwd --stdin $USER &> /dev/null
                echo "$USER add"
        fi
done
echo "done "

    首先定义一个USERNAMES变量(我之前习惯用下划线来建立变量,不过Linux中变量名好像都是大写字母,跟着大佬们走吧)获取`cat /opt/test1/user.txt`命令的结果,这里的`是间隔号(也就是键盘ESC键下面和~符号在一起的),代表执行这个命令,由于这种符号和单引号容易混淆,所以也可以使用$()命令来达到一样的效果,read从标准输入中获取内容,-p(prompt)提示,然后利用for循环,逐步取出文本每行内容,id $USER判断该用户名是否存在,我不需要其返回标准或者错误输出到控制台,所以利用&>将12输出全部重定向到/dev/null空间(类似于windows的回收站,但是不保留直接删除)中,$?返回上一条命令的结果,只要程序正常运行退出就会返回0,也就是说只要$?等于0,那么这个用户肯定是存在的,-eq运算符就是equal(同理,gt=>greater than等等),如果不等于0,那么这个用户不存在,使用useradd添加用户,然后使用管道符,将前面输入的pwd密码以标准输入的形式更新到USER。

成功添加用户。测试完成之后,删除用户及其在home目录下的文件夹:

userdel --remove --force zhang


    利用while循环完成一个猜数小游戏。

# !/bin/bash
PRICE=$(expr $RANDOM % 100)
TIMES=1
while true
do
        read -p "guess the price: " INT
        if [ $INT -eq $PRICE ]
        then
                echo "you are right, price is $PRICE. times is $TIMES"
                exit
        elif [ $INT -gt $PRICE ]
        then
                echo "lower than $INT."
        else
                echo "bigger than $INT."
        fi
let TIMES++
done

expr计算一个表达式,RANDOM变量会返回一个0~32767之间的随机数,除以100取余,也就是PRICE变量会在0~99之间,然后猜就完事了。


    利用case判断键盘输入的是数字、字母还是其他。

#!/bin/bash
read -p "enter a key: " KEYNAME
case $KEYNAME in
        [a-zA-Z])
                echo "is string"
                ;;
        [0-9])
                echo "is number"
                ;;
        *)
                echo "ohters"
                ;;
esac

测试如下:

可能唯一需要解释的就是结尾的esac单词吧,记也记不住,其实就是case反着写,不用记,就像上面的if语句结尾是fi一样。

 

    Linux中的命令实在太多,作为凡人,确实不可能完全背熟所有命令,所以高效的利用帮助文档就很重要了,之前在写expect命令时也简单介绍了下手册之类的工具,但是自己也是一知半解,这次整理的详细些。

    方法一:--help选项。适合查询曾经用过,但是忘记选项和参数的命令。

date --help
# 输出如下:
Usage: date [OPTION]... [+FORMAT]
  or:  date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
Display the current time in the given FORMAT, or set the system date.

可以看到Usage中列出了执行命令的语法,有两种语法,一种是直接执行返回日期,也可增加+FORMAT参数返回指定格式日期,另外一种就是设置日期时间,格式为MMDDhhmm。

继续下翻,里面有各参数含义的释义,继续往下,则是格式的说明:

FORMAT controls the output.  Interpreted sequences are:...

    

    方法二:man page。一般完全不了解这个命令的时候使用手册。

    注意:内容比较多的时候,可以使用/?来搜索,类似于vim中,输入斜杠或者问号,进入末行模式,再次输入关键词,使用n/N进行前后搜索的切换。

man date
#进入到手册界面
#命令名称及简单介绍
NAME
#概要,介绍基本用法
SYNOPSIS
#用法一
  date [OPTION]... [+FORMAT]
#用法二
  date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
#详细说明用法谈到的选项和参数,建议仔细查看
DESCRIPTION
#-d为短参数,--date为完整选项
  -d, --date=STRING
  display time described by STRING, not 'now'
#示例
EXAMPLES
#上面--date提到的STRING格式说明
DATE STRING
  # e.g:date -d "next Monday" 下个周一为3月1号
  # Mon Mar  1 00:00:00 CST 2021
#与这个命令相关额环境参数说明
ENVIRONMENT
#作者
AUTHOR
#著作权法额保护
COPYRIGHT # =>GNU GPL
#还可以在哪里查到与date相关额说明文件
SEE ALSO

# 还有些参数这里面没有,也一并写在这里
OPTIONS#针对SYNOPSIS中列举的所有可用的选项说明
COMMANDS#当这个程序在执行的时候,可以在此程序中执行的命令

刚进入到这个手册,我们可以看到DATE(1),这个数字(1)是有含义的,表明是“一般用户可使用的命令”,以下为数字参照表,更具体的内容含义可使用man man查看:

1--User Commands 用户命令,用户在shell环境中可以操作的命令或可执行文件。
2--System Calls 系统内核,系统内核可调用的函数与工具等,即由内核提供的函数。如open,write之类的(通过这个,可以很方便的查到调用这个函数时需要加什么头文件)。
3--C Library Functions,一般常用的函数(funtion)与函数库(library),大部分为C的函数库(libc)。
4--Devices and Special Files 设备文件的说明,通常是/dev下的文件。
5--File Formats and Conventions 配置文件或某些文件的格式 。
6--Games 游戏,给游戏留的,由各个游戏自己定义。
7--Miscellanea 杂项,惯例与协议等,例如linux文件系统,网络协议,ASCII code等说明。
8--System Administration tools and Deamons 系统管理员可以用的管理命令。
9--跟kernel有关的文件。

再来测试一个

man null
#数字4,表示其是一个设备文件
FILES
#这个程序或数据所使用或参考或链接到的某些文件
#可以看到熟悉的/dev/null和/dev/zero文件


    man page的数据存放位置,可以使用man man查看,在FILES一项中,可以看到我的手册是在/usr/share/man中,也可以通过/etc/man_db.conf配置文件进行修改。

    使用-f参数可以查看更多与命令(该命令必须为完整名称!)相关的信息,如下:

man -f man
# 等价于whatis passwd
#输出
man (7)     - macros to format man pages
man (1)     - an interface to the on-line reference manuals
man (1p)    - display system documentation

可能你使用man -f man参数会提示nothing appropriate,可以尝试使用以root权限使用mandb命令创建或更新手册页索引缓存。

    可以看到与man有关的手册有三个,我们可以使用如下命令查看不同的手册,一般来说,man man显示的是序号较小的手册,具体查找顺序定义在man_db.conf配置文件当中。

man 1 man
man 7 man


    也许,某个时候突然想查询某个命令,但是却怎么想不起来命令的名称,只记得某个关键词,可以使用-k参数模糊搜索,例如:

man -k passwd
# 等价于 apropos passwd


    另外,Linux还提供了info工具用于查询命令,可以使用info info查看。

还可以直接进入到/usr/share/doc目录下查看说明文件,一般这个目录下的说明文件不仅告诉你怎么做,还会有相关的原理说明。