[5分钟快速入门]bash脚本编程
[5分钟快速入门]bash脚本编程
- linux下,对大型项目的管理,bash脚本自动化是很重要的一环,需要重点深入,深入!
shell语言的笔记【和c、go、java不一样的地方】
1、shell语言的变量在读取的时候是需要加$开头
- 【与c、go、java不同的地方】
【准备编口诀记忆】Shell脚本中$0、$?、$!、$$、$*、$#、$@等的意义
举例:在Python中,可以使用
sys.argv来访问命令行参数。argv[0]是脚本的名称,而argv[1]及后续的值是传递的参数。【Python的sys.argv的编号和shell的编号是一样的!】
➜ ~ python3 bb.py 11 22
argv[0]: bb.py
argv[1]: 11
argv[2]: 22
argv[3]: 不存在
➜ ~ cat bb.py
import sys
# 打印argv的第0到第3个值
for i in range(4):
try:
print(f"argv[{i}]: {sys.argv[i]}")
except IndexError:
print(f"argv[{i}]: 不存在")记忆方法:都是$开头
| 变量 | 意义 |
$0 | 当前脚本的名称,Shell本身的文件名 |
$1~$n | 添加到Shell的各参数值。$1是第1参数、$2是第2参数…。我觉得的$0到$n可以统一起来,这万一还不是那种类似其他语言的args参数 |
| $* | - 所有位置参数(如果没有使用--option选项,则包括脚本名称) - 所有参数列表。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 |
| $# | 位置参数的数量(不包括脚本名称),添加到Shell的参数个数 |
| $@ | - 所有位置参数(不包括脚本名称)【在封装scp的时候用】 - 所有参数列表。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。 |
| $- | 使用Set命令设定的Flag一览 |
$?是前一个命令的退出状态,最后运行的命令的结束代码(返回值), 比如
if [ $? -eq 0 ]
then
echo "进入${target_path} 目录成功!"
else
echo "进入${target_path} 目录失败!"
exit 1
fi
$$是当前进程的进程ID,Shell本身的PID(ProcessID)
比如你在shell中执行echo $$就能看到!此外,你ps -aux也能看到!
$!是Shell最后运行的后台Process【进程】的PID【很有用】
比如echo $! >> ${base_path}/log/pidlist
$#位置参数的数量(不包括脚本名称),添加到Shell的参数个数
举例:
[work@~/demo/exp]$bash demo.sh 111 222
demo.sh
111
222
111 222
2
30353
111 222
hB
[work@~/demo/exp]$cat demo.sh
echo "$0"
echo "$1"
echo "$2"
echo "$*"
echo "$#"
echo "$$"
echo "$@"
echo "$-"shell脚本生成一个随机数
内置变量$RANDOM,RANDOM 是 Bash 的一个内建函数(而不是常量),会返回一个在区间 [0, 32767] 内的整数,若超过5位可以加个固定10位整数,然后进行求余。
# 获取一个系统随机数
val=$RANDOM
sleepTime=$(($val%3600))2、条件判断:shell的判断语句【与c、go、java大不一样!】
shell的判断-条件测试,判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成测试过程,评估布尔声明,以便用在条件性执行中
- 若真,则返回0
- 若假,则返回1
测试命令(3种方法):
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]- 注意:EXPRESSION前后必须有空白字符
- 这个就和C、go、java的编码规范很不一样!我们的c、go、java的编码规范都是说()前后不要有空格,但是shell真就很不一样
- 而且,shell脚本是
[]而不是()
方法1:test命令
长格式的例子
test "$A" == "$A" && echo "Strings are equal"
test "$A" -eq "$A" && echo "Integers are equal"方法2:简写格式的例子
[ "$A" == "$B" ] && echo "Strings are equal"
[ "$A" -eq "$B" ] && echo "Integers are equal"2、分支语句:典型的复合命令
常见的
case ... in ... esac语句
if ... elif ... else语句
while .... do ... done语句
for ... in ...; do ... done,判断文件或文件夹是否存在
if [ ! -d "/data/" ];then
mkdir /data
else
echo "文件夹已经存在"
fiif [ -d "/data/" ];then
echo "文件夹存在"
else
echo "文件夹不存在"
fiif [ -f "/data/filename" ];then
echo "文件存在"
else
echo "文件不存在"
fi常用的文件比较符
-e 判断对象是否存在
-d 判断对象是否存在,并且为目录
-f 判断对象是否存在,并且为常规文件
-L 判断对象是否存在,并且为符号链接
-h 判断对象是否存在,并且为软链接
-s 判断对象是否存在,并且长度不为0
---【感觉下面的很适合。shell驱动go去执行,然后没权限操作go产出的文件】
-r 判断对象是否存在,并且可读
-w 判断对象是否存在,并且可写
-x 判断对象是否存在,并且可执行
---
-O 判断对象是否存在,并且属于当前用户
-G 判断对象是否存在,并且属于当前用户组
-nt 判断file1是否比file2新 [ "/data/file1" -nt "/data/file2" ]
-ot 判断file1是否比file2旧 [ "/data/file1" -ot "/data/file2" ]附录1、bash的数组数据结构
#!/bin/bash
# 使用圆括号定义数组
origincode=(
"first/1.txt"
"first/2.txt"
)
curcode=(
"second/1.txt"
"second/2.txt"
)复合命令
函数function name() {....}都属于复合命令。
【坑】shell脚本如何换行,比如比如-conf=
注意
注意事项:
- ( 也就是换行前所在的那一行的)反斜杠
\后面不能有多余的空格、注释、Tab之类的,否则无效
为了避免这类问题: - 使用纯文本编辑器,确保
\后面是没有任何字符(空格或 Tab)。 - 可以在命令行中用
cat -A script.sh检查有没有隐藏的空格或 Tab(Tab 会显示为^I)。
正确写法,我们的\之后无空格、无 Tab
some_command \
--conf=config.yaml \
--opt=onnohup 也支持使用 \ 换行,写法和普通 shell 命令一样,只要换行位置正确、没有空格或 Tab 误用即可。
nohup python3 train.py \
--conf=config.json \
--epochs=100 ƒ\
--batch-size=32 \
> train.log 2>&1 &其他示例
python3 run.py \
--mode=train \
--conf=./config/long_file_path.json \
--verbose典型错误写法 1:反斜杠后有空格
some_command \ # ❌ 这里反斜杠后面跟了空格,会报错
--conf=config.yaml会报错或行为异常,因为 shell 认为 \ (带空格)不是续行。
典型错误写法 2:反斜杠后有 Tab
some_command \ # ❌ 这里是 Tab 键,同样不能被识别为换行
--conf=config.yaml同样会导致 \ 换行失效,具体表现可能是语法错误,或者 shell 把它当成两行独立命令
[必备]bash的防御式编程-借助wait命令
借助wait命令,监测日志输出,解决php的多进程,可能出现进程挂掉,但是子进程没结束,这种特殊情况
场景1:Linux 批量修改文件名(前缀或后缀)
添加前缀c-
for i in `ls`; do mv -f $i `echo "c-"$i`; done