bashcov - 如果子程序被 python 调用则不起作用
bashcov - does not work if subprogram is called by python
我安装了 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 [[ "" == "" ]]
then
echo no args
else
echo args
fi
./sub.sh
$ cat sub.sh
#! /usr/bin/env bash
set -e
if [[ "" == "" ]]
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 [[ "" == "" ]]
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,因为我破解了 bashcov 以使用 stderr 而不是自定义文件描述符...它确实如此bash 版本早于 4.1
# 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 不会。有人知道是否有办法改变它吗?
感谢评论和回答:
这个有效:
替换:
subprocess.run(["./sub.sh"])
和
subprocess.Popen(["./sub.sh"], close_fds=False).communicate()
可以为 Popen
关闭该功能,但不能为 run
和 close_fds
我安装了 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 [[ "" == "" ]]
then
echo no args
else
echo args
fi
./sub.sh
$ cat sub.sh
#! /usr/bin/env bash
set -e
if [[ "" == "" ]]
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 [[ "" == "" ]]
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,因为我破解了 bashcov 以使用 stderr 而不是自定义文件描述符...它确实如此bash 版本早于 4.1
# 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 不会。有人知道是否有办法改变它吗?
感谢评论和回答:
这个有效:
替换:
subprocess.run(["./sub.sh"])
和
subprocess.Popen(["./sub.sh"], close_fds=False).communicate()
可以为 Popen
关闭该功能,但不能为 run
和 close_fds