有一个业务脚本,用lua写的,运行在debian linux下面,要求不可以启动多次。
linux下控制一个程序不可以启动多次方法挺多,这一次用了从ps读进程的方法。
很简单,只要一条语句,而且不需要特殊的权限,普通用户就可以使用。
os.execute(“test
(psax|grepluatest.lua|grep
(
p
s
a
x
|
g
r
e
p
l
u
a
t
e
s
t
.
l
u
a
|
g
r
e
p
(which lua)|wc -l) -eq 1”)
判断这个函数返回值是不是为0就可以了,为0表示正常,即只有一个实例在运行。
简单解释一下。
()是取括号里命令执行的结果。psax是取当前系统正在运行的进程。|是管道,就是把前面一个命令的输出重定向到后一个命令的输入。grepluatest.lua就是找出psax的结果中包含luatest.lua的行,当然,不同的脚本要换成相应脚本的名字。whichlua的意思是找出lua在哪个目录下,或者也可以直接写成/usr/bin/lua。grep
(
)
是
取
括
号
里
命
令
执
行
的
结
果
。
p
s
a
x
是
取
当
前
系
统
正
在
运
行
的
进
程
。
|
是
管
道
,
就
是
把
前
面
一
个
命
令
的
输
出
重
定
向
到
后
一
个
命
令
的
输
入
。
g
r
e
p
l
u
a
t
e
s
t
.
l
u
a
就
是
找
出
p
s
a
x
的
结
果
中
包
含
l
u
a
t
e
s
t
.
l
u
a
的
行
,
当
然
,
不
同
的
脚
本
要
换
成
相
应
脚
本
的
名
字
。
w
h
i
c
h
l
u
a
的
意
思
是
找
出
l
u
a
在
哪
个
目
录
下
,
或
者
也
可
以
直
接
写
成
/
u
s
r
/
b
i
n
/
l
u
a
。
g
r
e
p
(which lua)的意思是找出其中包含lua解释器的行,如果不加这一条的话会有干扰。还是看个例子吧。
建立一个文件luatest.lua:
!/usr/bin/lua
os.execute(“ps ax|grep luatest.lua”)
执行一下./luatest.lua,结果是这样的
3331 pts/0 S+ 0:00 /usr/bin/lua ./luatest.lua
3332 pts/0 S+ 0:00 sh -c ps ax|grep luatest.lua
3334 pts/0 S+ 0:00 grep luatest.lua
也就是说我们用grep检查的命令也会被ps列出来,这样一个实例就会有多条了,不符合我们的要求。那是不是我们检查一下应该有3行数据就是说明只有单一实例呢?也不行。除了grep会带来干扰,如果在crontab里调用这个脚本也会有干扰,如果在远程机器用ssh调用也会有干扰。所以我们必须把干扰去掉。
这就是为什么要加上grep
(whichlua)的原因,加上这一行,就可以把多余的过滤掉,只剩下一行。再用os.execute(“psax|grepluatest.lua|grep
(
w
h
i
c
h
l
u
a
)
的
原
因
,
加
上
这
一
行
,
就
可
以
把
多
余
的
过
滤
掉
,
只
剩
下
一
行
。
再
用
o
s
.
e
x
e
c
u
t
e
(
“
p
s
a
x
|
g
r
e
p
l
u
a
t
e
s
t
.
l
u
a
|
g
r
e
p
(which lua)”)测试一下,得到
3606 pts/0 S+ 0:00 /usr/bin/lua ./luatest.lua
这下差不多了,最后一个wc -l是统计行数,这样获得的结果就是当前进程中此脚本运行的数量,这个数量用test -eq 1来判断是不是为1,如果为1,说明当前只有一个脚本的实例在运行,整个命令执行成功,返回码为0,这时os.execute的返回值也为0,可以用lua直接判断了。