Linux下npx concurrently将stdout替换为socket的替代方案问询
问题背景
concurrently是一款Node.js工具,能同时执行多个命令并给输出打标签,示例用法:
npx concurrently -n "frontend,backend" "launch_frontend.sh" "launch_backend.sh"
但在Linux系统中,它启动的子进程stdout会指向socket,而macOS下stdout还是常规的文件描述符1。这就导致像npx concurrently "echo 'hello world' > /dev/stdout"这样的命令在macOS能正常运行,Linux下却失败——直接执行echo命令在两个系统都没问题。
原因是Linux下通过concurrently运行时,/dev/stdout指向/proc/self/fd/1,而这个路径对应的是socket(比如socket:[12345]),不是常规的终端设备(比如/dev/pts/0)。现在要运行的程序会尝试打开/dev/stdout,没法修改程序代码,又不想用会禁用日志标签功能的--raw参数,得找其他Linux下的解决办法。
解决方案
使用
script命令模拟伪终端script命令可以创建一个伪终端(PTY),让程序认为自己在终端环境中运行,此时/dev/stdout会指向伪终端设备而非socket。用法:npx concurrently "script -q -c './your-program' /dev/null"-q:静默模式,不输出script本身的启动/退出信息-c:指定要执行的程序/dev/null:把script的日志输出丢到空设备,不需要保存会话日志
使用
unbuffer命令生成伪终端unbuffer是expect工具包的一部分(需要先通过apt install expect或yum install expect安装),它会给程序分配伪终端,同时禁用输出缓冲。用法:npx concurrently "unbuffer ./your-program"这个方法同样能让程序的/dev/stdout指向正常的终端设备,同时保留concurrently的日志标签功能。
手动重定向到当前终端
如果是在交互式终端环境下运行,可以先获取当前终端的路径,然后把程序的输出重定向到该终端:CURRENT_TTY=$(tty) npx concurrently "./your-program > $CURRENT_TTY 2>&1"这种方法直接绕开了concurrently创建的socket,让程序的输出直接指向当前终端,不过如果concurrently的输出被重定向到文件或其他地方,这个方法可能不适用。
内容的提问来源于stack exchange,提问作者Toby Corkindale

