我已经安装了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程序直接调用另一个时,它在某种程度上是有效的。我还尝试使用以下方式调用子流程
shell=True
结果是子程序没有错误和覆盖信息。
有人知道它是如何组合在一起的吗?为什么文件描述符在直接从main调用的bash程序中有效,而在从python调用的程序中无效?
我知道它在python调用的子程序中使用了bashcov,因为我破解了bashcvo,使用了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
得到了这个:
我几乎可以在不使用的情况下显示正在发生的事情
bashcov
完全。
这实际上只是一个关于python和linux的问题。也许我应该提出一个新问题:
我创建了一组新的示例程序,如下所示:
==> m.sh <==
#! /usr/bin/env bash
set -e
exec 3<>messages
ls -l /proc/$$/fd/
echo bash program called directly
./s.sh
==> r.py <==
import subprocess
import sys
import os
print("python program:")
subprocess.run(["ls", "-l", "/proc/%s/fd/" % os.getpid()])
print("bash program called by python:")
subprocess.run(sys.argv[1:], check=True)
==> s.sh <==
#! /usr/bin/env bash
set -e
ls -l /proc/$$/fd/
这就是结果
$ ./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不会。有人知道是否有办法改变这一点吗?