Open ghost opened 7 years ago
Great question! Bashcov relies on the xtrace
ability and the $LINENO
special variable to get the current line number. I just tried that on a Debian machine (which uses Dash as the POSIX shell):
$ cat test.sh
#!/bin/sh -x
echo $LINENO
$ ./test.sh
+ echo
So -x
(i.e. xtrace
) is supported but not $LINENO
. It seems it's disabled at compilation time.
Are you using a *BSD variant and does it support $LINENO
by default?
As expected, it fails badly without $LINENO
support: https://travis-ci.org/infertux/bashcov/jobs/191911884
It'd be interesting to compile Dash with $LINENO
support or try with KornShell...
@infertux -- dash 0.5.9.1
on Arch Linux comes with support for $LINENO
, and I was able to get bashcov
working with a few changes:
$PS4
needs to use $0
instead of $BASH_SOURCE
Bashcov::BashInfo.bash_xtracefd?
to return false
, since parsing $BASH_VERSINFO
doesn't tell us anything of interest when using dash
:)-x
to the command since dash
does not recognize SHELLOPTS=xtrace
: bashcov --bash-path /usr/bin/dash -- -x ./test.sh
Happy to take a crack at updating bashcov
to support shells that recognize $LINENO
. Maybe we could check during the initialization proces whether the program provided as --bash-path
expands $LINENO
to an integer?
That's great news. Thanks a lot @BaxterStockman.
$0
behaves slightly differently than $BASH_SOURCE
so we'll need to make sure it doesn't introduce regressions.
I see sh
is just a symlink to bash
on Arch:
% ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Dec 10 18:55 /bin/sh -> bash
I wonder if Bash runs in "pseudo" POSIX-compliant mode when called that way. The man page says you can pass --posix
to Bash.
I should have some time to work on this next week but please feel free to take a crack at it! That would be most welcomed :)
So it looks like it will be difficult to support POSIX shells in all but the most basic scenario of generating coverage stats for a single script. As far as I have been able to determine, dash
, ksh
, and mksh
provide no means of globally enabling execution tracing a la SHELLOPTS=xtrace
-- the only way to turn on tracing is with set -x
, which isn't inherited by scripts invoked from the "parent" script.
One possiblity is to provide "shim" scripts -- something like <bashcov root>/exe/{sh,dash,ksh,mksh}
-- that simply exec
the correct shell with the -x
option, passing through the contents of ARGV
. By prepending the exe
dir to PATH
, scripts with shebangs like #!/usr/bin/env sh
will use the shim scripts and therefore have execution tracing enabled. Of course, this approach won't work for scripts that use shebangs like #!/bin/sh
.
which isn't inherited by scripts invoked from the "parent" script
Same result for me. Bummer.
One possiblity is to provide "shim" scripts [...] Of course, this approach won't work for scripts that use shebangs like #!/bin/sh.
Great idea but yeah I'm afraid most sh scripts out there use #!/bin/sh
and not #!/usr/bin/env sh
. That being said, they should be able to switch to #!/usr/bin/env sh
without breaking anything in theory if they really want to use Bashcov. It looks like it's the only reliable option we have anyway. Would this be helpful in your case @WillemMali?
PS: Thanks again for your help @BaxterStockman :)
Ping @WillemMali
Sorry for not responding, I guess I missed the email.
Yes, that would be helpful. I could then wrap bashcov
to run on a copy of my script with the #!
modified, if I were really stubborn about wanting to use #!/bin/sh
:^)
bashcov() {
$tmp="$(mktemp)"
{ echo "#!/usr/bin/env sh"; tail -n+2 "$0"; } | cat > "$tmp"
shift
status=0
exec bashcov "$tmp" "$@" || status="$?"
rm "$tmp"
exit "$status"
}
... I'm not sure if I'm spending too much or too little of my time writing shell scripts.
Holy moly, TIL that kcov is using some LD_PRELOAD
trickery to override execve
calls and inject the -x
flag into the argument vector when the command name is /bin/bash
, /bin/sh
, /bin/ash
or /bin/dash
. That's... brilliant(/depraved). Not sure it's worth supporting something similar for Bashcov, but it's a neat idea.
Nice find! Though I feel like overriding LD_PRELOAD
is more depraved than brilliant IMHO... unless you're doing it for debugging purposes.
Hi, I'm looking for a tool to test a rather large sh script (it's around a 1000 lines atm). I have one main script for which I want to generate coverage (preferably also for the large command strings that are passed to
xargs
to get aroundread
not supporting\0
-separation in most implementations), but I also have a collection of test scripts also written insh
.Does bashcov have support for pure
sh
scripts? Would you recommend I use bashcov for this?