如何写一个类似于ls的命令(如何写一个类似于ls的命令)
目录
需求:
脚本实现思路
要点:
需求:
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
,免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com