3

I am writing some bash scripts that I want to deliver and mantain with a deb package. As I need to list the dependencies of the package, I would like to find all executables that the scripts are calling and find which packages do they belong.

Is it possible to list all executables called by a bash script?

EDIT

To better clarify: say that my script is

#!/bin/sh
echo "hello"
cat file.txt | grep -v "STRING"
if [ -d $SOMEDIR ]; then
    ./something.sh
else
    ./something_else.sh
fi

I would like to analyze the content of such script and the output should be:

echo
cat
grep
./something.sh
./something_else.sh

(regardless of any other possible executable called by the other two *.sh scripts)

alephz3r0
  • 99
  • 7
  • Well, what do you mean by "executable"? Execute flag is 1 for owner? Or something more accurate? Maybe look here: https://stackoverflow.com/questions/10319652/check-if-a-file-is-executable – ErniBrown Mar 09 '18 at 16:20
  • 1
    You would have to isolate the *command* part of each line of code and do a `type` on it, but there are complications with command and process substitution (`$( )` ` ` `<()` `>()`) , you would have to write a code parser, which is a lot of work. Since you are writing the scripts, would it not be simpler if you just kept a record as you went along? You could track `vfork/execve` calls using something like `strace`, but that would be runtime dependant. – cdarke Mar 09 '18 at 16:34
  • 1
    not that easy, commands can be in variables, other scripts, etc. – Diego Torres Milano Mar 09 '18 at 16:38
  • right guys, maybe it's easier to keep track of "executables" manualy as I write the scripts – alephz3r0 Mar 09 '18 at 16:45
  • Possible duplicate of [Search for executable files on Unix](https://stackoverflow.com/questions/4458120/unix-find-search-for-executable-files), [How can I find only the executable files under a certain directory](https://superuser.com/q/38981/173513), [How to find binary executables within a directory](https://unix.stackexchange.com/q/1484/56041), etc. – jww Mar 09 '18 at 16:53
  • 1
    @jww: Searching for invocations by a script, not existing in the filesystem. – user unknown Mar 09 '18 at 16:59
  • Maybe you can setup a minimal linux system in a chroot-environment, where you can test the script to catch every non standard program. I guess it would be hard to write a program, which could not been defeated, to find every program invoked. How long is your script? – user unknown Mar 09 '18 at 17:03
  • @userunknown - The dups provided were for the titular question. The question is worse than that... its one of those YES/NO questions that should have been asked on another site. – jww Mar 09 '18 at 17:08
  • 1
    In principle, you cannot in general find them (because the executable could be in some variable, previously computed with an unpredictable computation). – Basile Starynkevitch Mar 09 '18 at 17:16
  • @jww: The title is about finding executables in a script, not with a script. My first impression was too, that this is a job for find, not for a script, but then I realized what is asked for. And the dupes aren't dupes for the question. Not even for the title. They are mismatches. They don't help. The parrot is dead. :) – user unknown Mar 09 '18 at 17:17
  • Possible duplicate of [Check if a file is executable](https://stackoverflow.com/q/10319652/608639) – jww Dec 06 '19 at 07:09

1 Answers1

2

You can run your scripts through strace and check the executables invoked

$ strace -qqfe execve ./script.sh

and you'll get something like

execve("./script.sh", ["./script.sh"], [/* 81 vars */]) = 0
[pid 27651] execve("/bin/grep", ["grep", "hello"], [/* 80 vars */]) = 0
...
Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
  • But that will not find such scripts, which were not invoked, based on otherwise different conditions, won't it? – user unknown Mar 09 '18 at 16:57
  • 1
    @userunknown It will only find scripts that _did_ ran. It won’t find those that could potentially run if different conditions were met. That would involve complicated code analysis (think about `exec("somescript"+random())`). – bfontaine Mar 09 '18 at 17:00
  • I thought about it. That's why I asked. – user unknown Mar 09 '18 at 17:04
  • but the set of scripts is known (AFAIU) as they are in the deb package being created – Diego Torres Milano Mar 09 '18 at 17:39
  • This works for the script you posted, of course, you have to cover all the cases (like `$SOMEDIR` present or not) but you should have that kind of coverage on your tests already – Diego Torres Milano Mar 09 '18 at 20:57
  • There are also external side effects -- did running `somecommand` cause `path/to/anotherfile` to be created although it doesn't exist now, and you can't know just by inspecting `somecommand` because ... turtles all the way down. – tripleee Mar 09 '18 at 23:45