可重入的函数是安全的。不可重入的函数,每次调用返回的结果,可能是不一致的,即使每次传入的参数是一样的。编程语言里的函数如此,那么linux的shell脚本是不是可重入的呢?答案是:未必。其中,有很大部分的shell脚本是不可重入的。这自然带出问题:如何防止shell脚本的重入?
---------------------------------------摘自某某不会装AC的码农笔录
这里讨论的脚本重入问题,是说在同一时刻,同时调用2次同一个脚本文件。很多时候,我们希望的结果可能有2种,分别是:
1. 多次同时调用同一个脚本文件,只有最先那次调用可以正常跑完成,其余的中断退出;
2. 多次同时调用同一个脚本文件,按照调用次序,一次执行完成了,再继续执行下次(这里隐含了,当前调用的脚本在运行时,其他的脚本调用都被阻塞住,等待当前调用结束);
遇到这个情形,我们自然首先想到了锁,或者类似锁的机制,可以从2个角度下手,一个是从调用者这里下手,一个是从被调用的脚本下手。
从调用者出发,典型的例子是,在crontab里运用flock防止重复执行:
flock -xn /home/wll/test.lock -c "/home/wll/test.sh"
注意:必须确保test.lock和test.sh这2个文件真实存在,test.lock文件可以是一个空文本文件;参数“-n”是非阻塞。
从被调用的脚本下手:
#!/bin/bash
exec 4<>/home/wll/test.lock
flock -n 4
[ $? -eq 1 ] && { echo fail; exit; }
echo $$
sleep 100
echo "finish my shell"
注意:
1. exec的参数语法,请自行查找,后面的数字是[3, 9] 之间的整数;
2. 这里的“-n”是非阻塞的,一旦发现test.lock文件被占用,就打印”echo“,然后退出脚本;
3. 加锁影响的范围是,从开始上锁,到整个脚本执行退出;
最后
1. 在调用flock的时候,可以不使用“-n”参数,阻塞在flock语句行,直到锁文件占用被其他进程释放;
2. 在调用flock的时候,可以使用“-w”参数,设定在阻塞超过多少秒后,从flock语句行主动返回;
3. 在c/c++代码里,也可以调用flock函数,做以上类似的操作,但是需要特别小心,在程序里被阻塞并造成死锁的情况;