bashcov-如果python调用子程序,则该程序不起作用

bashcov-如果python调用子程序,则该程序不起作用,python,linux,bash,subprocess,code-coverage,Python,Linux,Bash,Subprocess,Code Coverage,我已经安装了bashcov。。为了测量一组bash脚本中的代码覆盖率: $ bash --version GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu) ... $ bundle exec bashcov --version ba

我已经安装了bashcov。。为了测量一组bash脚本中的代码覆盖率:

$ bash --version                                                                                                      GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)
...
$ bundle exec bashcov --version
bashcov 1.8.2
这完全符合预期:

$ cat main.sh 
#! /usr/bin/env bash

set -e

if [[ "$1" == "" ]]
then
  echo no args
else
  echo args
fi

./sub.sh
$ cat sub.sh 
#! /usr/bin/env bash

set -e

if [[ "$1" == "" ]]
then
  echo no args in subprogram
else
  echo args in subprogram
fi
$ bundle exec bashcov ./main.sh 
no args
no args in subprogram
Run completed using bashcov 1.8.2 with Bash 5.0, Ruby 2.7.0, and SimpleCov 0.15.1.
Coverage report generated for /bin/bash ./main.sh to ~/bashcov/coverage. 7 / 9 LOC (77.78%) covered.
我得到这些html报告:

因此,它完全可以调用另一个bash程序,并测量它的覆盖率


然而

当我试图把Python程序放在中间时,事情并不像我想的那样工作:

$ cat main.sh 
#! /usr/bin/env bash

set -e

if [[ "$1" == "" ]]
then
  echo no args
else
  echo args
fi

python3 -u sub.py

$ cat sub.py 
import subprocess

print("running subprograms")

subprocess.run(["./sub.sh"])
$ # and leave sub.sh the same as above
$ bundle exec bashcov ./main.sh 
no args
running subprograms
bash: BASH_XTRACEFD: 8: invalid value for trace file descriptor
+BASHCOV>f4697250-c3da-4086-.....set -e
+BASHCOV>f4697250-c3da-4086-.....[[ '' == '' ]]
+BASHCOV>f4697250-c3da-4086-.....echo no args in subprogram
no args in subprogram
Run completed using bashcov 1.8.2 with Bash 5.0, Ruby 2.7.0, and SimpleCov 0.15.1.
Coverage report generated for /bin/bash ./main.sh to ~/bashcov/coverage. 4 / 9 LOC (44.44%) covered.
我们没有子程序的覆盖率信息:


所以

如果从python调用,它放在环境中的文件描述符“8”在子程序中不再有效,但当一个bash程序直接调用另一个bash程序时,它在某种程度上是有效的。我还尝试使用
shell=True
调用子流程,结果是没有错误,也没有子程序的覆盖信息

有人知道它是如何结合在一起的吗?为什么文件描述符在直接从main调用的bash程序中有效,而在从python调用的bash程序中无效


我知道它在python调用的子程序中使用了bashcov,因为我对bashcov进行了黑客攻击,使其使用stderr而不是自定义文件描述符。。。对于早于4.1的bash版本,它会这样做

      # Older versions of Bash (< 4.1) don't have the BASH_XTRACEFD variable
+      if Bashcov.bash_xtracefd? and false
-      if Bashcov.bash_xtracefd?
        options[fd] = fd # bind FDs to the child process

        env["BASH_XTRACEFD"] = fd.to_s
      else
        # Send subprocess standard error to @xtrace.file_descriptor
        options[:err] = fd

        # Don't bother issuing warning if we're silencing output anyway
        unless Bashcov.mute
          write_warning <<-WARNING
            you are using a version of Bash that does not support
            BASH_XTRACEFD. All xtrace output will print to standard error, and
            your script's output on standard error will not be printed to the
            console.
          WARNING
        end

这就是结果

$ ./m.sh 
total 0
lrwx------ 1 me me 64 Apr 15 22:43 0 -> /dev/pts/2
l-wx------ 1 me me 64 Apr 15 22:43 1 -> pipe:[188295]
lrwx------ 1 me me 64 Apr 15 22:43 2 -> /dev/pts/2
lr-x------ 1 me me 64 Apr 15 22:43 255 -> /home/me/bashcov/m.sh
lrwx------ 1 me me 64 Apr 15 22:43 3 -> /home/me/bashcov/messages
bash program called directly
total 0
lrwx------ 1 me me 64 Apr 15 22:43 0 -> /dev/pts/2
l-wx------ 1 me me 64 Apr 15 22:43 1 -> pipe:[188295]
lrwx------ 1 me me 64 Apr 15 22:43 2 -> /dev/pts/2
lr-x------ 1 me me 64 Apr 15 22:43 255 -> /home/me/bashcov/s.sh
lrwx------ 1 me me 64 Apr 15 22:43 3 -> /home/me/bashcov/messages
python program:
total 0
lrwx------ 1 me me 64 Apr 15 22:43 0 -> /dev/pts/2
l-wx------ 1 me me 64 Apr 15 22:43 1 -> pipe:[188295]
lrwx------ 1 me me 64 Apr 15 22:43 2 -> /dev/pts/2
lrwx------ 1 me me 64 Apr 15 22:43 3 -> /home/me/bashcov/messages
bash program called by python:
total 0
lrwx------ 1 me me 64 Apr 15 22:43 0 -> /dev/pts/2
l-wx------ 1 me me 64 Apr 15 22:43 1 -> pipe:[188295]
lrwx------ 1 me me 64 Apr 15 22:43 2 -> /dev/pts/2
lr-x------ 1 me me 64 Apr 15 22:43 255 -> /home/me/bashcov/s.sh

bash将所有文件描述符向下传递给子进程,但python没有。有人知道有没有办法改变这一点吗?

多亏了一条评论,答案如下:

这项工作:

替换:

subprocess.run(["./sub.sh"])


使用
close\u fds

Hi@Alex028502-so
bashcov xx.sh
bashcov实际上是脚本在其中运行的shell,可以为
Popen关闭该功能,但不能运行
run
。。。但是,在python中,它使用默认的shell而不是bashcov。。。如果python代码有
subprocess.run([“bashcov.”/sub.sh“])
或类似的内容,那么输出可能会如预期的那样…它使用bashcov。我将编辑这个问题以显示我是如何知道的。如果我不能解决这个问题,我可能仍然会使用你的变通方法!我想您遇到了我在中描述的相同问题(
子流程
有助于关闭所有打开的文件描述符,除非您要求它执行其他操作)。我切换到Popen,它成功了!谢谢我应该检查这些选项,而不是只是运行opopsii,实验是用<代码>制作< <代码> > <代码> Ruby 中间,调用BASH子程序,并且运行良好。js与python有相同的问题,因此我在这里询问了如何将文件描述符传递给node
subprocess.run(["./sub.sh"])
subprocess.Popen(["./sub.sh"], close_fds=False).communicate()