如何让System.cmd调用ack/rg时在STDIN等待输入时正常终止?
问题原因分析
当执行System.cmd("ack", [""])或System.cmd("rg", [""])时,ack/rg会将空字符串参数判定为需要从标准输入读取搜索内容,而System.cmd默认会维持子进程的标准输入通道处于打开状态,导致子进程一直等待输入,最终造成IEx挂起。而传入空列表时,工具会直接输出帮助文本后退出,因此能正常返回结果。
解决方案
1. 显式关闭子进程标准输入
通过System.cmd的:stdin选项传入:close,立即关闭标准输入,让工具因读取不到输入而终止进程:
# 处理ack {message, errlevel} = System.cmd("ack", [""], stdin: :close) # 处理rg {message, errlevel} = System.cmd("rg", [""], stdin: :close)
这样就能正常获取工具的返回结果,不会出现挂起。
2. 替换空字符串参数为工具原生语法
如果需求是搜索空字符串,直接使用工具的正则匹配语法,避免触发标准输入读取逻辑:
# rg匹配空行 {message, errlevel} = System.cmd("rg", ["^$"]) # ack匹配空行 {message, errlevel} = System.cmd("ack", ["^$"])
3. 异步执行(可选)
如果担心阻塞当前进程,可以用Task异步包裹执行,但核心仍需配合:stdin: :close避免子进程挂起:
task = Task.async(fn -> System.cmd("ack", [""], stdin: :close) end) {message, errlevel} = Task.await(task)
内容的提问来源于stack exchange,提问作者Onorio Catenacci
相关产品推荐
相关产品推荐

