bash/shell编程学习(3)
接上节继续,
1. 从键盘读取输入内容
1 2 3 | #!/bin/bash read -p 'please input something:' input echo 'your input:' $input |
运行效果:
1 2 3 | . /read1 .sh please input something:123 your input: 123 |
2. while循环及case分支
1 2 3 4 5 6 7 8 9 10 11 12 | #!/bin/bash printf '\nplease input a number or character, press "q" or "Q" to quit:\n' while true do read reply case $reply in q|Q) echo 'bye!' ; break ;; #结束循环 [A-Za-z]*) echo 'you input a character:' $reply;; #如果输入的是纯英文字符 [0-9]*) echo 'you input a number:' $reply;; #如果输入的是纯数字 esac printf 'please go on ...\n' done |
运行效果:
1 2 3 4 5 6 7 8 9 10 11 | . /read1 .sh please input a number or character, press "q" or "Q" to quit: 123 you input a number: 123 please go on ... qwe you input a character: qwe please go on ... Q bye! |
3. 文件操作相关
3.1 文件权限及所有者
ll (2个小写字母L)用于列出当前目录的所有文件(及目录)详细信息
1 2 3 4 | [deploy@deploy myservice]$ ll total 4 drwxrwxr-x. 2 deploy deploy 6 Jan 21 17:10 a -rw-r--r--. 1 root root 40 Jan 21 14:41 test .txt |
解读下这些输出,最开始的10个字符,拆分一下,其格式为:
类型(1位) 所属用户权限(3位) 所属用户组权限(3位) 其它组权限(3位)
所以:
d rwx rwx r-x 表示这是一个目录(第1位是d, Directory的首字母),然后所属用户有读(r,Read的首字母)、写(w,Write的首字母)、执行(x,代表eXecute)权限,所属用户组也同样具有所有权限,其它用户组具有读、执行权限。
- rw- r-- r-- 表示这是一个普通文件(第1位是-,表示普通文件),然后所属用户有read、write权限,所属用户组及其它组只能读。
注:第1位,除了d及-外,还有l表示link,说明这是符号链接,另外b表示块(block)设备,c表示字符(character)设备
继续看后面的输出,后面的二个字符串,即 deploy deploy 表示的是 所属用户及所属用户组,换句话说 目录 a 属于用户deploy及用户组deploy,而 test.txt属于用户root及用户组root
可以通过chown修改文件所属用户,示例:
1 | sudo chown deploy test .txt |
表示将test.txt的所属用户修改为deploy,因为该命令需要较高权限,所以前面加sudo切换到root身份,执行以后,再ll检测
1 2 3 4 | [deploy@deploy myservice]$ ll total 4 drwxrwxr-x. 2 deploy deploy 6 Jan 21 17:10 a -rw-r--r--. 1 deploy root 40 Jan 21 14:41 test .txt |
可以看到test.txt的所属用户已经变成deploy了。
chmod用于修改用户及目录权限,示例:
1 2 3 4 5 | [deploy@deploy myservice]$ chmod +w test .txt [deploy@deploy myservice]$ ll total 4 drwxrwxr-x. 2 deploy deploy 6 Jan 21 17:10 a -rw-rw-r--. 1 deploy root 40 Jan 21 14:41 test .txt |
chmod +w test.txt表示将test.txt的所属用户及所属用户组的权限增加写(w,write)权限
1 2 3 4 5 | chmod a+w test .txt [deploy@deploy myservice]$ ll total 4 drwxrwxr-x. 2 deploy deploy 6 Jan 21 17:10 a -rw-rw-rw-. 1 deploy root 40 Jan 21 14:41 test .txt |
这次在+w前加了一个a,表示all,即给所有人都增加了test.txt的写权限
1 2 3 | [deploy@deploy myservice]$ chmod u-w test .txt [deploy@deploy myservice]$ ll test .txt -r--rw-rw-. 1 deploy root 40 Jan 21 14:41 test .txt |
猜一下,也能大概知道u-w的意思,u即user缩写,-表示去掉权限,所以u-w表示将所属用户的write权限去掉,类似的
1 2 3 | [deploy@deploy myservice]$ chmod g-r test .txt [deploy@deploy myservice]$ ll test .txt -r---w-rw-. 1 deploy root 40 Jan 21 14:41 test .txt |
g-r表示将所属用户组的read权限去掉。
另外,从计算机内部的二进制来看,权限可以用3位2进制表示,从左向右依次为: 读、写、执行,所以111表示所有权限,101表示读及执行权限,000表示没任何权限,再考虑到 所属用户、所属用户组、其它组,也就是说有3组二进制,因此
chmod a+rwx 可以简化为 chmod 777
注:777是10进制表示,转换成权限2进制,即 111 111 111
1 2 3 | [deploy@deploy myservice]$ chmod 777 test .txt [deploy@deploy myservice]$ ll test .txt -rwxrwxrwx. 1 deploy root 40 Jan 21 14:41 test .txt |
类似的,如果要去掉所有人的所有权限
1 2 3 | [deploy@deploy myservice]$ chmod -777 test .txt [deploy@deploy myservice]$ ll test .txt ----------. 1 deploy root 40 Jan 21 14:41 test .txt |
3.2 文件测试
1 2 3 | #!/bin/bash [ -f "test.txt" ] && echo 'test.txt is exists' [ ! -f 'abc.txt' ] && echo 'abc.txt is not exist' |
上面这段表示,表示如果文件test.txt存在,则输出test.txt is exists,类似的,如果文件abc.txt不存在,则输出abc.txt is not exists
再增加一些判断:
1 2 3 4 5 6 | #!/bin/bash [ -f "test.txt" ] && echo 'test.txt is exists' [ ! -f 'abc.txt' ] && echo 'abc.txt is not exist' [ -x "test.txt" ] || echo 'test.txt can not execute' [ -d "a" ] && echo "a is directory" [ -d "a" ] && [ -r "a" ] && echo "a is directory and can read " |
完整的文件判断条件收集如下:
1 2 3 4 5 6 7 8 9 10 11 | -e filename 如果 filename存在,则为真 (e即Exist的首字母) -d filename 如果 filename为目录,则为真 (d即Directory的首字母) -f filename 如果 filename为常规文件,则为真 (f即File的首字母) -L filename 如果 filename为符号链接,则为真 (L即Link的首字母,注意这个是大写的) -r filename 如果 filename可读,则为真 (r即Read的首字母) -w filename 如果 filename可写,则为真 (w即Write的首字母) -x filename 如果 filename可执行,则为真 (x即eXecute) -s filename 如果文件长度不为0,则为真(可记忆为Substance的意思) -h filename 如果文件是软链接,则为真 filename1 -nt filename2 如果 filename1比 filename2新,则为真(-nt 可记忆为new than) filename1 -ot filename2 如果 filename1比 filename2旧,则为真(-nt 可记忆为old than) |
4. 获取其它命令的输出
1 2 3 4 5 | cmd_pwd=` pwd ` cmd_date=` date "+%Y-%m-%d %H:%M:%d" ` current_dir=${cmd_pwd} current_time=${cmd_date} |
注意:命令字符串两端的不是单引号,而是`(即:键盘最左上角esc键下的~键)
输出:
1 2 | 当前目录: /Users/yjmyzz 当前时间:2016-01-21 18:13:21 |
5. 获取nohup的进程id
先建一个app-test.sh来模拟应用程序,内容如下:
1 2 3 | #!/bin/bash echo 'I want to sleep 100 second' sleep 100 |
这段代码,啥也不干,上来就sleep 100秒
再建一个app-run.sh来模拟后台启动app-test,内容如下:
1 2 3 4 | #!/bin/bash echo 'app is starting...' nohup . /app-test .sh > /dev/null 2>&1 & echo 'ok,the pid is :' $! |
测试一下:
1 2 3 4 5 | ➜ ~ . /app-run .sh app is starting... ok,the pid is :3168 ➜ ~ ps -ef| grep app- test .sh 501 3168 1 0 6:26PM ttys001 0:00.01 /bin/bash . /app-test .sh |
即: $!可以取到nohup后台启动的程序对应的pid
将前面写到的这些知识,来一个综合练习:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | #!/bin/bash cmd_pwd=` pwd ` pwd_dir=${cmd_pwd} pid_file=${pwd_dir} /my .pid #启动 sub_start() { printf "starting..." if [ -w "${pid_file}" ]; then echo ${pid_file} ' has already exists' else nohup . /netty-sample > /dev/null 2>&1 & pid=$! echo $! > ${pid_file} sleep 2 printf 'ok!\n' fi } #停止 sub_stop() { printf "stopping..." if [ -w "${pid_file}" ]; then pkill -F ${pid_file} sleep 2 printf 'ok!\n' else printf '\n' ${pid_file} ' NOT exists' fi } #查看状态 sub_status(){ if [ -w "${pid_file}" ]; then printf "running.\n" else printf "NOT running.\n" fi } case $1 in start) sub_start ;; stop) sub_stop ;; restart) printf "restarting...\n" sub_stop sleep 1 sub_start sleep 1 sub_status ;; status) sub_status ;; *) printf "usage: $0 {start|stop|restart|status}\n" exit 1 ;; esac exit 0 |
这是一段通用的启动shell脚本,大意是启动指定应用(上面的代码中,待启用的应用为netty-sample,大家可以自行修改)时,先找到进程id,然后保存到pid文件中,这样后面就通过检测pid是否存在,来判断程序是否在运行中,也可用于结束程序或重启程序。
6、编写自己的linux服务
linux下的服务,只要在/etc/rc.d/init.d/下放一个自己的shell脚本就可以了,参考内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #! /bin/bash # chkconfig: 2345 10 90 # description: myservice .... #. /etc/init.d/functions desc= 'my-service' cmd=` date "+%Y-%m-%d %H:%M:%S" ` case "$1" in start) printf '%s is starting...' ${desc} sleep 1 printf 'ok!\n' echo ${cmd} >> /opt/myservice/test .txt ;; stop) printf '%s is stopping...' ${desc} sleep 1 printf 'ok!\n' ;; status) printf '%s is ok!\n' ${desc} ;; restart|reload|force-reload) $0 stop $0 start ;; *) echo $ "Usage: $0 {start|stop|status|restart|reload|force-reload}" exit 2 esac exit 0 |
代码不复杂,启动时在指定目录写个文件而已,将其保存成myservice.sh,赋予执行权限,应该就可以service myservice start|stop|restart|status了,很简单吧。
(注:第3,4行的注释不能删除,否则后面加入开机启动时会报错。)
如果想让myservice服务开机即自动启动,可以执行
1 | sudo chkconfig --add myservice |
加好后,可以尝试重启下机器,看指定目录下的文件是否有生成,如果生成且写入了新内容,表明服务确实运行了。
另外:chkconfig 不加任何参数,可以查看当前有哪些服务配置了开机自动启动。如果要从开机启动的服务列表中删除,chkconfig --del myservice.
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步