os.execute没有继承父的fds
我有一个类似于这里描述的问题:
防止fork()复制套接字
基本上,在我的Lua脚本中,我正在生成另一个脚本:
无论如何都不需要与我的脚本通信
我的脚本完成后继续运行
是第三方程序,我无法控制的代码
问题是我的Lua脚本打开一个TCP套接字来侦听特定端口并在它退出后,尽管有一个明确的
server:close()
,孩子(或更具体地说是它的孩子)保持套接字并保持端口打开(处于LISTEN状态)阻止我的脚本再次运行。
这是演示问题的示例代码:
require('socket')
print('listening')
s = socket.bind("*", 9999)
s:settimeout(1)
while true do
print('accepting connection')
local c = s:accept()
if c then
c:settimeout(1)
local rec = c:receive()
print('received ' .. rec)
c:close()
if rec == "quit" then break end
if rec == "exec" then
print('running ping in background')
os.execute('sleep 10s &')
break
end
end
end
print('closing server')
s:close()
如果我运行上面的脚本并且echo quit | nc localhost 9999
一切正常 - 程序退出并关闭端口。
但是,如果我执行echo exec | nc localhost 9999
程序退出,但端口被生成的sleep
(由netstat -lpn
确认)阻止,直到它退出。
我如何以最简单的方式解决这个问题,最好不要添加任何额外的依赖项。
没有找到相关结果
已邀请:
3 个回复
咳累录酬
在
中运行
的事实,事实证明,它能够关闭文件描述符,如下所示: http://linux.die.net/man/1/ash(重定向部分) http://www.gnu.org/software/bash/manual/bashref.html#Redirections 例如(在
中测试):
所以在我基于
的例子中,它足以代替:
有:
这将关闭所有文件描述符,包括我的服务器套接字,然后执行实际命令(此处为
),以便在脚本退出后不会占用端口。它还有照顾
和
重定向的奖励。 这比解决
的限制更加紧凑和简单,并且不需要任何额外的依赖性。感谢#uclibc,我从嵌入式Linux工作人员那里得到了一些关于最终shell语法的精彩帮助。
枫湃揩乾纲
,我不确定你是否能够这样做。你可能会成功将它移到
之前,因为你无论如何都要(20((但你可能不会在你的真实程序中这样做)。为清晰起见编辑:实际问题是,在这种情况下,您唯一产生子进程的地方是使用
,并且您无法控制睡眠的子环境,其中所有内容都是从主程序继承的,包括套接字和文件描述符。 因此,在POSIX上执行此操作的规范方法是使用
而不是
(aka,
),因为
/
将在执行期间挂起到当前进程状态,并且您将无法在阻止时关闭它在子过程中。 因此,建议采用luaposix,并使用其
和
功能,并在
ed子进程中调用
。不应该这么糟糕,因为你已经依靠
使用外部包装了。 编辑:这是使用luaposix进行大量评论的代码:
这会在调用
之前关闭子进程中的套接字,并且
输出显示当父进程退出时系统正在不再侦听端口9999。 附:当执行失败时,行
抱怨一次类型问题。我实际上并不知道lua,所以你必须解决这个问题。 :)此外,
可能会失败,返回-1。为了完整性,也可以在主代码中检查它。
苦诫
请注意,我没有在luaposix源中找到FD_CLOEXEC常量,因此您可能还需要手动添加它。