如何写一个类似于ls的命令?(shell进阶)

简介: 如何写一个类似于ls的命令?(shell进阶)

需求:

sleep 作为daemon进程运行,可以以配置文件的方式指定睡眠时长。 以及要实现切换mode start/kill 。

脚本实现思路

先使用getopt实现对参数以及选项的解析。(-- 后面解析的是非选项型参数)

对解析到的参数进行判断是否合法?

例如配置文件是否为空?

参数是否可以一起使用?

将解析到的参数保存在变量中以便在后续的功能中使用。

给默认值,像ls,如果不写选项,肯定会有默认选项的

sleep的默认就是start模式,start模式必须跟一个时间或者配置文件,否则应该提示用户输入时间。

sleep默认的pid输出文件为/tmp/mysleep.pid

再实现脚本的具体功能、例如start、kill..

要点:

有的选项是需要有默认值的

有的选项不能同时出现,例如-s 和 -k不能同时出现。sleep时长的配置指定时间或者配置文件即可。

详细的注释已在脚本中,欢迎大家点赞拍砖。

#!/usr/bin/bash
# author: ninesun
# date: 2022年1月4日22:27:23
VERSION=1.0
usage(){
    cat <<'EOF'
Usage: $0 [options] [TIME]
    options:
        -s,--start    start
        -k,--kill     kill
        -p,--pidfile  pidfile
        -c,--config   config
        --help        help
        --version     version
EOF
}
pstreeStatus(){
  pstree -p | grep sleep
}
# -------------------------------------  getopt对选项和参数的处理START--------------------
# -o 解析短选项 skhvp:c:,p:c:中的冒号代表是参数型选项,其后一定要跟参数,例如 -p "123" -c "456"
# -l 解析长选项 start,kill,pidfile:,config:,help,version. 选项之间逗号隔开,冒号含义和-o选项一致.
# -- 之后都为参数,$@ 取的当前脚本所传进去的参数列表。作为getopt的parameter。 getopt按照 -o -l的格式进行解析。
# 解析之后的参数列表赋给parameters
parameters=`getopt -o skhvpt:c: -l start,kill,pidfile:,config:,help,version,status -- "$@"`
[ $? -ne 0 ] && exit 1 # getopt 如果解析失败,退出脚本.
eval set -- "$parameters" # set 的--选项代表将命令行参数转换为位置参数$1 $2.. 以便后续脚本使用方便
while true;do
    case "$1" in #使用shift命令将参数 一直往左移动,使case一直处理第一个位置的参数
        -p|--pidfile) pidfile=$2; shift 2;; #-p指定pidfile存放的位置. 对于选项型参数,选型和参数两个位置,因此要shift 2
        -s|--start) [ -z "$mode"] && mode="start" || exit 1; shift;; # -z 判断mode是否为空,为空则默认为start。
        -k|--kill)  [ -z "$mode"] && mode="kill" ||  echo "-s and -k can't use together..."; exit 1; shift;; # -s和-k不能一起使用
        -c|--config) config=$2; shift 2;; # sleep 时间的配置文件
    -t|--status) pstreeStatus;exit ;;
        -h|--help) usage;exit ;;
        -v|--version) echo $VERSION;exit;;
        --) #-- 代表解析到非选项型参数,即 睡眠时间。 时间可以放在任何位置. 
            shift # 向左移动一个位置,将--移出,是第一个参数为时间
            time=$1 # ,shift之后, $1为时间参数
      break # 已经解析到getopt格式化之后的最后一个参数了。因此break 直接跳出while循环.
      ;; 
        *)
            usage;exit 4 #
      ;;
    esac
done
# 如果没有给任何选项,必须默认给一个操作模式
[ -z "$mode" ] && mode="start" # 默认是start
# pid文件,默认为/tmp/mysleep.pid
[ -z "$pidfile" ] && pidfile=/tmp/mysleep.pid
# -------------------------------------  对sleep 时间参数的处理 START---------------------
# -s模式下config和TIME给且仅给一个,应该判断同时存在,是否存在配置?、是否存在参数? 三种情况
#-k模式下可以不需要$time
case "$mode" in
    start)
        if [ -n "$config" -a -n "$time" ];then # [ -n "$config"  ]config 非空(非0),返回0(true)。以-a为分隔 ,左边和右边进行逻辑与。 相与为真代表传了两个时间参数.
            echo "-c(--config) and TIME can't use together..."
            exit 1
        elif [ -n "$config" ];then #config 如果非空,read 读取,read 
      if [ -r "$config" ];then #配置文件是否可读
        read line <$config
        [ -z "$line" ] && exit 1
        #"${line//[0-9]/}"替换line变量中的数字为空,正常情况应该为空,如果非空代表pid包含非数字.
        [ -n "${line//[0-9]/}" ] && { echo "config file must contain num...";exit 1; } 
        time=$line
      else
        echo "config unreadable"
        exit 1
      fi
        elif [ -n "$time" ];then
            [ -n "${time//[0-9]/}" ] && { echo "time must contain num...";exit 1; }
        else
            echo "give me a time to sleep..."
            exit 1
        fi
        ;;
    kill)
        ;;
    *)
        usage;exit 1
esac 
echo mode: $mode
echo time: $time
echo pidfile: $pidfile
# ------------------------------------- 实际业务主逻辑Start-------------------------------
# 启动进程
startmysleep(){
    pidfile=$1
    time=$2
    ( sleep $time & echo $! ) >>"${pidfile}" # 小括号会在一个子shell中执行. 所以echo $!打印当前sleep执行的pid要放在小括号里面。
}
# 杀sleep:找到pid文件,然后杀掉进程
killmysleep(){
    pidfile=$1
    if [ -r "${pidfile}" ];then
        while read pid;do
            [ -z "$pid" ] && exit 1 # 如果为pid空则退出
            #  -n "${pid//[0-9]/}" 检查pid是否合法
      #两个斜杠//代表贪婪替换。替换pid张红的数字,pid一定是只有数字的,如果pid中含有字母或空,则替换之后肯定为空,-n 如果不为空代表pid中有非法字符则退出.
      [ -n "${pid//[0-9]/}" ] && exit 1 
            kill $pid && rm -rf ${pidfile}
        done <${pidfile}
        return 0
    fi
    return 1
}
case "$mode" in
    start)
        startmysleep $pidfile $time
    ;;
    kill)
        killmysleep $pidfile
    ;;
    *)
        usage
esac
目录
相关文章
|
19天前
|
Web App开发 Java Linux
Linux之Shell基本命令篇
Linux之Shell基本命令篇
Linux之Shell基本命令篇
|
1月前
|
安全 Shell Linux
【Shell 命令集合 系统管理 】Linux 锁定终端 vlock命令 使用指南
【Shell 命令集合 系统管理 】Linux 锁定终端 vlock命令 使用指南
36 1
|
1月前
|
监控 Shell Linux
【Shell 命令集合 系统管理 】Linux 显示当前登录到系统的用户信息 who命令 使用指南
【Shell 命令集合 系统管理 】Linux 显示当前登录到系统的用户信息 who命令 使用指南
43 1
|
1月前
|
监控 Shell Linux
【Shell 命令集合 系统管理 】Linux 显示目前登入系统的用户信息 w命令 使用指南
【Shell 命令集合 系统管理 】Linux 显示目前登入系统的用户信息 w命令 使用指南
45 2
|
1月前
|
存储 Shell Linux
【Shell 命令集合 系统管理 】Linux 修改用户的属性和配置 usermod命令 使用指南
【Shell 命令集合 系统管理 】Linux 修改用户的属性和配置 usermod命令 使用指南
35 1
|
7天前
|
存储 Shell 数据安全/隐私保护
ZooKeeper【基础知识 04】控制权限ACL(原生的 Shell 命令)
【4月更文挑战第11天】ZooKeeper【基础知识 04】控制权限ACL(原生的 Shell 命令)
25 7
|
14天前
|
分布式计算 Hadoop Shell
Hadoop【基础知识 04】【HDFS常用shell命令】(hadoop fs + hadoop dfs + hdfs dfs 使用举例)
【4月更文挑战第4天】Hadoop【基础知识 04】【HDFS常用shell命令】(hadoop fs + hadoop dfs + hdfs dfs 使用举例)
28 5
|
1月前
|
存储 Shell 数据安全/隐私保护
【Shell 编程指南】Shell read命令 (从标准输入读取数值)
【Shell 编程指南】Shell read命令 (从标准输入读取数值)
25 0
|
1月前
|
网络协议 Shell Linux
【Shell 命令集合 系统管理 】Linux 查询域名的注册信息 whois命令 使用指南
【Shell 命令集合 系统管理 】Linux 查询域名的注册信息 whois命令 使用指南
49 1
|
1月前
|
存储 Shell Linux
【Shell 命令集合 系统管理 】Linux 显示当前登录用户的用户 whoami命令 使用指南
【Shell 命令集合 系统管理 】Linux 显示当前登录用户的用户 whoami命令 使用指南
49 1