使用node.js将文件描述符传递给子进程 [英] pass on file descriptors to child process with node.js

查看:81
本文介绍了使用node.js将文件描述符传递给子进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了在我的一个项目中使用 bashcov ,我需要一种将所有文件描述符从node.js传递到子进程的方法.

我创建了以下测试程序:

  $ head -n20 m.sh r.js s.sh==>m.sh< ==#!/usr/bin/env bash设置-e执行3消息回声,看看何时可以看到我们创建的文件描述符从主要bash程序回显:ls -l/proc/$$/fd/回声从bash子程序直接回显:./s.sh回声节点r.js ./s.shexec 3&-==>r.js< ==const run = function(cmd){返回require('child_process').spawnSync(cmd [0],cmd.slice(1),{stdio:继承",});}console.log('from javascript program:');运行(['ls','-l',`/proc/$ {process.pid}/fd/`]);console.log('\ n来自js调用的bash子程序:');运行(process.argv.slice(2))==>s.sh< ==#!/usr/bin/env bash设置-els -l/proc/$$/fd/ 

主程序 m.sh 列出其所有文件描述符,然后调用bash程序,我将其称为子程序". s.sh 还将列出其所有fds.然后,我调用一个列出其可用fds的js程序 r.js ,然后使用 child_process lib再次调用 s.sh .

这是结果:

  $ ./m.sh看看何时可以看到我们创建的文件描述符从主要的bash程序:总计0lrwx ------ 1 me me 64 Apr 16 12:16 0->/dev/pts/2l-wx ------ 1 me me 64 Apr 16 12:16 1->管道:[256648]lrwx ------ 1 me me 64 Apr 16 12:16 2->/dev/pts/2lr-x ------ 1 me me 64 Apr 16 12:16 255->/home/me/bashcov/m.shlrwx ------ 1 me me 64 Apr 16 12:16 3->/home/me/bashcov/messages从bash子程序直接调用:总计0lrwx ------ 1 me me 64 Apr 16 12:16 0->/dev/pts/2l-wx ------ 1 me me 64 Apr 16 12:16 1->管道:[256648]lrwx ------ 1 me me 64 Apr 16 12:16 2->/dev/pts/2lr-x ------ 1 me me 64 Apr 16 12:16 255->/home/me/bashcov/s.shlrwx ------ 1 me me 64 Apr 16 12:16 3->/home/me/bashcov/messages从javascript程序:总计0lrwx ------ 1 me me 64 Apr 16 12:16 0->/dev/pts/2l-wx ------ 1 me me 64 Apr 16 12:16 1->管道:[256648]lrwx ------ 1 me me 64 Apr 16 12:16 10->anon_inode:[事件投票]lr-x ------ 1 me me 64 Apr 16 12:16 11->管道:[256661]l-wx ------ 1 me me 64 Apr 16 12:16 12->管道:[256661]lrwx ------ 1 me me 64 Apr 16 12:16 13->anon_inode:[eventfd]lrwx ------ 1 me me 64 Apr 16 12:16 14->anon_inode:[事件投票]lr-x ------ 1 me me 64 Apr 16 12:16 15->管道:[258179]l-wx ------ 1 me me 64 Apr 16 12:16 16->管道:[258179]lrwx ------ 1 me me 64 Apr 16 12:16 17->anon_inode:[eventfd]lr-x ------ 1 me me 64 Apr 16 12:16 18->/dev/空lrwx ------ 1 me me 64 Apr 16 12:16 19->anon_inode:[事件投票]lrwx ------ 1 me me 64 Apr 16 12:16 2->/dev/pts/2lr-x ------ 1 me me 64 Apr 16 12:16 20->管道:[258182]l-wx ------ 1 me me 64 Apr 16 12:16 21->管道:[258182]lrwx ------ 1 me me 64 Apr 16 12:16 22->anon_inode:[eventfd]lrwx ------ 1 me me 64 Apr 16 12:16 3->/home/me/bashcov/messageslrwx ------ 1 me me 64 Apr 16 12:16 4->anon_inode:[事件投票]lr-x ------ 1 me me 64 Apr 16 12:16 5->管道:[258177]l-wx ------ 1 me me 64 Apr 16 12:16 6->管道:[258177]lr-x ------ 1 me me 64 Apr 16 12:16 7->管道:[258178]l-wx ------ 1 me me 64 Apr 16 12:16 8->管道:[258178]lrwx ------ 1 me me 64 Apr 16 12:16 9->anon_inode:[eventfd]从js调用的bash子程序中:总计0lrwx ------ 1 me me 64 Apr 16 12:16 0->/dev/pts/2l-wx ------ 1 me me 64 Apr 16 12:16 1->管道:[256648]lrwx ------ 1 me me 64 Apr 16 12:16 2->/dev/pts/2lr-x ------ 1 me me 64 Apr 16 12:16 255->/home/me/bashcov/s.sh 

您可以看到,从node.js调用 s.sh 时,它无权访问我创建的文件描述符 3 .bash将其传递给它所调用的bash程序以及它所调用的节点程序,但是节点没有.

我刚刚在python中遇到了这个问题( bashcov-如果python调用了子程序,则不起作用),而解决方案竟然是添加参数 close_fds = False .( os.system()与os.popen()相比,使用bash进程替代时:ls:无法访问'/dev/fd/63':没有此类文件或目录)

如果我将本实验中的js程序替换为ruby或make程序,则效果很好.

有没有办法告诉node.js的 child_process 在child_process上传递所有打开的文件描述符?

解决方案

stdio:'inherit'替换为 stdio:[0,1,2,3] .'inherit'是每个[0,1,2] 的简写.rel ="nofollow noreferrer">文档,因此,如果您也希望传递FD 3,则需要手动添加它.除了手动创建包含所有数字的数组之外,我没有其他方法可以告诉它继承每个FD.

In order to use bashcov in one of my projects, I need a way to pass on all file descriptors from node.js to a child process.

I have created these test programs:

$ head -n20 m.sh r.js s.sh
==> m.sh <==
#! /usr/bin/env bash

set -e

exec 3<>messages

echo see when we can see the file descriptor we created
echo from main bash program:
ls -l /proc/$$/fd/
echo
echo from bash subprogram called directly:
./s.sh
echo
node r.js ./s.sh

exec 3>&-

==> r.js <==
const run = function(cmd) {
  return require('child_process').spawnSync(cmd[0], cmd.slice(1), {
    stdio: 'inherit',
  });
}

console.log('from javascript program:');
run(['ls', '-l', `/proc/${process.pid}/fd/`]);
console.log('\nfrom bash subprogram called from js:');
run(process.argv.slice(2))


==> s.sh <==
#! /usr/bin/env bash

set -e

ls -l /proc/$$/fd/

The main program m.sh list all of its file descriptors, and then call a bash program that I have referred to as "subprogram" s.sh which also lists all of its fds. Then I call a js program r.js which lists its available fds, and then calls s.sh again using the child_process lib.

This is the result:

$ ./m.sh
see when we can see the file descriptor we created
from main bash program:
total 0
lrwx------ 1 me me 64 Apr 16 12:16 0 -> /dev/pts/2
l-wx------ 1 me me 64 Apr 16 12:16 1 -> pipe:[256648]
lrwx------ 1 me me 64 Apr 16 12:16 2 -> /dev/pts/2
lr-x------ 1 me me 64 Apr 16 12:16 255 -> /home/me/bashcov/m.sh
lrwx------ 1 me me 64 Apr 16 12:16 3 -> /home/me/bashcov/messages

from bash subprogram called directly:
total 0
lrwx------ 1 me me 64 Apr 16 12:16 0 -> /dev/pts/2
l-wx------ 1 me me 64 Apr 16 12:16 1 -> pipe:[256648]
lrwx------ 1 me me 64 Apr 16 12:16 2 -> /dev/pts/2
lr-x------ 1 me me 64 Apr 16 12:16 255 -> /home/me/bashcov/s.sh
lrwx------ 1 me me 64 Apr 16 12:16 3 -> /home/me/bashcov/messages

from javascript program:
total 0
lrwx------ 1 me me 64 Apr 16 12:16 0 -> /dev/pts/2
l-wx------ 1 me me 64 Apr 16 12:16 1 -> pipe:[256648]
lrwx------ 1 me me 64 Apr 16 12:16 10 -> anon_inode:[eventpoll]
lr-x------ 1 me me 64 Apr 16 12:16 11 -> pipe:[256661]
l-wx------ 1 me me 64 Apr 16 12:16 12 -> pipe:[256661]
lrwx------ 1 me me 64 Apr 16 12:16 13 -> anon_inode:[eventfd]
lrwx------ 1 me me 64 Apr 16 12:16 14 -> anon_inode:[eventpoll]
lr-x------ 1 me me 64 Apr 16 12:16 15 -> pipe:[258179]
l-wx------ 1 me me 64 Apr 16 12:16 16 -> pipe:[258179]
lrwx------ 1 me me 64 Apr 16 12:16 17 -> anon_inode:[eventfd]
lr-x------ 1 me me 64 Apr 16 12:16 18 -> /dev/null
lrwx------ 1 me me 64 Apr 16 12:16 19 -> anon_inode:[eventpoll]
lrwx------ 1 me me 64 Apr 16 12:16 2 -> /dev/pts/2
lr-x------ 1 me me 64 Apr 16 12:16 20 -> pipe:[258182]
l-wx------ 1 me me 64 Apr 16 12:16 21 -> pipe:[258182]
lrwx------ 1 me me 64 Apr 16 12:16 22 -> anon_inode:[eventfd]
lrwx------ 1 me me 64 Apr 16 12:16 3 -> /home/me/bashcov/messages
lrwx------ 1 me me 64 Apr 16 12:16 4 -> anon_inode:[eventpoll]
lr-x------ 1 me me 64 Apr 16 12:16 5 -> pipe:[258177]
l-wx------ 1 me me 64 Apr 16 12:16 6 -> pipe:[258177]
lr-x------ 1 me me 64 Apr 16 12:16 7 -> pipe:[258178]
l-wx------ 1 me me 64 Apr 16 12:16 8 -> pipe:[258178]
lrwx------ 1 me me 64 Apr 16 12:16 9 -> anon_inode:[eventfd]

from bash subprogram called from js:
total 0
lrwx------ 1 me me 64 Apr 16 12:16 0 -> /dev/pts/2
l-wx------ 1 me me 64 Apr 16 12:16 1 -> pipe:[256648]
lrwx------ 1 me me 64 Apr 16 12:16 2 -> /dev/pts/2
lr-x------ 1 me me 64 Apr 16 12:16 255 -> /home/me/bashcov/s.sh

You can see that inside the s.sh when it is called from node.js, it does not have access to file descriptor 3 which I have created. bash passes it on to the bash program it calls, and the node program it calls, but node does not.

I have just run into this issue with python (bashcov - does not work if subprogram is called by python) and the solution turned out to be to add the param close_fds=False. (os.system() vs. os.popen() when using bash process substitution: ls: cannot access '/dev/fd/63': No such file or directory)

If I replace the js program in this experiment with a ruby or make program, it works fine.

Is there a way to tell node.js's child_process to pass all the open file descriptors on the the child_process?

解决方案

Replace stdio: 'inherit' with stdio: [0, 1, 2, 3]. 'inherit' is shorthand for [0, 1, 2], per the documentation, so if you want FD 3 to be passed too, you need to add it manually. I don't see a way to tell it to inherit every FD other than manually creating an array with all of their numbers.

这篇关于使用node.js将文件描述符传递给子进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆