I have to troubleshoot this bash script called by a python script called by a program, all run in Ubuntu 18.04.

The python script and the program are black boxes. The only information I have is that they work fine, and the python script only fails when it calls the bash script because the script itself fails.

The bash script is very simple and works fine on its own, but fails whenever called from this script, which leads me to believe there is some sort of permissions error. The problem is, I need to find a way to get the error message it gives when it fails. How can I get that information in this situation?

Putting set -x and set -v does not spit out any information to the terminal when the bash script is run from the python script.

Here is the contents of the bash script:


echo "$1" >> /scripts/vomit
mv $1/*.mp4 .

The problem line is mv $1/*.mp4. If I comment out that line, the script works when called from the python script that is called by the program. I just don't know why the mv line is failing.

  • Is it Linux or macOS? – kenorb Dec 3 '19 at 22:01
  • It's Ubuntu 18.04. – Sidereal Dec 3 '19 at 22:03
  • Does the variable $1 expand to a relative or absolute file path? If it is a relative file path, does the Python script know where it is supposed to be run from? – GracefulRestart Dec 3 '19 at 22:14
  • What is the value of $1? Since it's used unquoted, it would be split on whitespaces and undergo filename globbing. Does it specify a directory in the current working directory of the script that actually exists? – Kusalananda Dec 3 '19 at 22:16
  • The value is '/var/bigbluebutton/published/presentation/5b64bdbe09fdefcc3004c987f22f163ca846f1ea-1574708322765/'. Believe I've tested with $1 in quotes, but re-testing. Recall that the bash script works fine if I run it on its own – Sidereal Dec 3 '19 at 22:17

Use strace command to debug a program with its all child processes.

For the new process:

strace -f command

For the existing process:

strace -fp PID

If you don't know your process id (as it's run too quickly), you can add sleep 20 at the beginning of your shell script, so you've time to find its PID via ps wuax | grep bash then use above command with found PID.

To filter output use -e. To save into the file use -o. To increase size of messages, use -s. For more help, run: man strace.

For better formatting, see: How to parse strace in shell into plain text?

Here is the practical example. Given the following myscript.sh file:

#!/bin/bash -x
echo "$1"

I've run the following command:

strace -f -e trace=execve,read,write -s1000 bash -x ./myscript.sh foo bar

which produced the following output:

execve("/bin/bash", ["bash", "-x", "./myscript.sh", "foo", "bar"], [/* 41 vars */]) = 0
read(3, "#!/bin/bash -x\necho \"$1\"\n", 80) = 25
read(255, "#!/bin/bash -x\necho \"$1\"\n", 25) = 25
write(2, "+ echo foo\n", 11+ echo foo
)            = 11
write(1, "foo\n", 4foo
)                    = 4
read(255, "", 25)                       = 0
+++ exited with 0 +++
|improve this answer|||||
  • Having trouble formatting this. If the actual command that kicks off the program is bbb-record --rebuild 5b64bdbe09fdefcc3004c987f22f163ca846f1ea-1574708322765, how do I fit that into this strace command? – Sidereal Dec 3 '19 at 22:29
  • 1
    -f follows all processes as a result of the fork, vfork and clone system calls, maybe the script is triggered using some different method. – kenorb Dec 3 '19 at 22:35
  • 1
    @Sidereal Another way: add sleep 20 to your bash script to give you some time, run ps wuax | grep bash, find its PID and try strace -fp PID. – kenorb Dec 3 '19 at 22:36
  • 1
    I would add the flag -o /tmp/strace.log to the strace command to have its output go to a file. In particular, look for an exec to the name of the bash script to make sure it is being called. – doneal24 Dec 3 '19 at 23:04
  • 1
    I got strace to work, thank you. Now the problem is deciphering its output... – Sidereal Dec 3 '19 at 23:08

If nothing is shown on the terminal, you can redirect output into the file, e.g.

For your entire script (all output) into the file (change it in Python):

./script.sh &> output.log

For the single command:

mv -v $1/*.mp4 . 2> errors.log

Also consider adding set -x or using #!/bin/bash -x.

To redirect all stdout and stderr to the file, see: Redirect stderr and stdout in Bash, which is:

# Close STDOUT file descriptor
exec 1<&-
exec 2<&-

# Open STDOUT as $LOG_FILE file for read and write.
exec 1<> output.log

# Redirect STDERR to STDOUT
exec 2>&1
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.