Linux下flock命令的一种使用方式
前言
偶然看到一块使用flock命令的shell,由于学识尚浅,第一眼没有理解其中结构,所以诞生这篇文章,先贴代码:
1 |
|
一开始没有看到上面的exec命令,只看到两个脚本里分别写了flock -w 2 200
,就在想这个200到底是什么
并且自己尝试在命令行里执行就会报错flock: 200: Bad file descriptor
然后当时以为是存在一个大家都可以访问的并且值为200的文件描述符,但这不可能啊,文件描述符fd是进程隔离,应该不会有这种情况!
之后带着疑惑查看了整个脚本,发现两个脚本中都有exec命令带有200的参数,深入学习后,解释一下这个代码:
1 |
|
那接下来就把依次用到的内容做个扩展整理
整理
注:这里基于Ubuntu24.04平台,标准bash shell
flock
1 | # flock -h |
- 首先参数的各种含义,没有特殊需要解释的,如果不理解百度即可
- flock是一个文件锁,重点是文件,哪怕是通过不同的文件描述符,只要文件是相同的,那就是同一个
- 而且flock是君子锁,非强制锁,哪怕获取锁失败,也不影响对应文件的读写使用
flock的常用方式
除了上面例子里先用exec命令重定向之外,还有一种常用的方式:
1 | lockfile=".lock" |
这里通过括号使用了匿名函数,并且将lockfile重定向到200的文件描述符,供匿名函数内使用,到这里有必要说明一下作用域和生命周期
- 上面通过exec进行重定向的文件描述符,作用域是整个脚本,脚本结束后文件描述符会被释放,整个脚本都可以使用这个文件描述符,生命周期也就是脚本的生命周期
- 刚刚通过匿名函数的方式打开的文件描述符,作用域是匿名函数内部,生命周期是匿名函数的生命周期,也就是匿名函数执行完成后,文件描述符就会被关闭
exec
首先说明的是,exec属于bash的内建命令,而flock是独立的二进制
1 | # which exec |
替换当前进程
exec 后跟其他命令,可以执行该命令,它和直接执行该命令的区别是:exec执行命令实际是替换命令,这期间不会新创建进程,pid等内容自然不会改变,并且由于当前进程命令已经被改变,所以exec之后的命令不会被执行
1 | echo "now is normal bash" |
重定向
文章中和flock命令搭配使用的场景,就是用的exec的重定向功能
网上的资料大家都说是exec的重定向功能,但是我认为重定向功能实际是 < 和 > 操作符完成的,因为它们才是真正的重定向符号
exec在这里起的作用应该只是执行 < 和 > 符号的功能而已
1 | exec 3<&0 # 将标准输入(文件描述符0)重定向到文件描述符3 |
注意:
‘<’ 操作符是读取重定向,也是标准输入重定向,后面如果要跟文件,则需要文件存在并且对当前用户有只读权限
‘>’ 和 ‘>>’ 操作符是写重定向,也是标准输出重定向,后面跟文件,文件可以不存在,它会自己创建,这两者的区别在于’>>’ 是追加写
三个操作符如果要跟文件描述符,前后不能有空格
一个进程默认打开三个文件描述符,标准输入0,标准输出1,标准错误2
括号
在shell脚本中,括号存在很多种用法,功能丰富,但是这里只列一种,代码块
1 | { ls } |
- 以上分别是用大括号和小括号列举的代码块,代码块中执行的均为ls命令,两者均可以理解为匿名函数
- 代码块要求括号和命令之间必须存在空格
- 大括号和小括号实现的代码块区别
- 小括号会另起一个shell进程去执行,而大括号则是当前shell进程执行
- 大括号里的变量在后续脚本中能继续使用,小括号里的则不行