0

I'm wondering if there a way of capturing a list of the processes executed on a non-interactive shell?

Basically I have a script which calls some variables from other sources and I want to see what the values of said variables are. However, the script executes and finishes very quickly so I can't capture the values using ps.

Is there a way to log processes and what arguments were used?

TIA Huskie

EDIT:

I'm using Solaris in this instance. I even thought about about having a quick looping script to capture the values being passed - but this doesn't seem very accurate and I'm sure executions aren't always being captured. I tried this:

   #!/bin/ksh

   while [ true ]
   do

   ps -ef | grep  $SCRIPT_NAME |egrep -v 'shl|lis|grep' >> grep_out.txt

   done

I'd use sleep but I can't specify any precision as all my sleep executables want an integer value rather than any fractional value.

Huskie69
  • 795
  • 3
  • 11
  • 31
  • There is no generic/portable way but depending on the Unix variant you are using, there might be a specific solution. – jlliagre Oct 01 '14 at 15:19

3 Answers3

3

Most shells can be invoked in debug mode, where each statement being executed is printed to stdout (or stderr) after variable substitution and expansion.

For Bourne like shells (sh, bash), debug is enabled with the -x option (as in bash -x myscript) or using the set -x statement within the script itself.

However, debugging only works for the 'current' script. If the script calls other scripts, these other scripts will not execute in debug mode. Furthermore, the code inside functions may not be executed in debug mode either - depends on the specific shell - although you can use set -x within a function to enable debug explicitly.

isedev
  • 18,848
  • 3
  • 60
  • 59
  • functions will inherit `-x` if they are in the current shell. And `-x` is limited in its useful output in cases where variables are assigned values dynamically (like loop variables, etc.). Still very useful though. – Etan Reisner Oct 01 '14 at 15:17
  • @EtanReisner with `bash`, agreed - but IIRC, not with Solaris `sh`. – isedev Oct 01 '14 at 15:19
  • Yes, my experience is specifically with `bash`. I cannot speak for other shells. – Etan Reisner Oct 01 '14 at 15:20
3

On Solaris:

truss -s!all -daDf -t exec yourCommand 2>&1 | grep -v ENOENT

On AIX and possibly other System V based OSes:

truss -s!all -daDf -t execve yourCommand 2>&1 | grep -v ENOENT

On Linux and other OSes supporting strace, you can use this command:

strace -ff -etrace=execve yourCommand 2>&1 >/dev/tty | grep -v ENOENT

In case the command you want to trace is already running, you can replace yourCommand by -p pid with pid being the process to be traced process id.

EDIT:

Here is a way to trace your running script(s) under Solaris:

for pid in $(pgrep -f $SCRIPT_NAME); do
    truss -s!all -daDf -t exec -p $pid 2>&1 | grep -v ENOENT > log.$pid.out &
done

Note that with Solaris, you might also use dtrace to get the same (and more).

jlliagre
  • 29,783
  • 6
  • 61
  • 72
  • Good example of `truss` for this use case. However, I would not use `dtrace` for this purpose, total overkill. – isedev Oct 03 '14 at 12:24
  • @isedev You shouldn't rule out `dtrace`. A carefully crafted `dtrace` script will have a substancially smaller overhead than `truss` and will catch all script executions, not just the ones happening during the `ps` call. – jlliagre Oct 03 '14 at 14:27
  • The OP wants a 'list of the processes executed on a non-interactive shell' (i.e. all child processes created by it - truss on exec(ve) is more than sufficient to obtain that). I use `dtrace` a lot, but in this case, it seems like using a sledgehammer to kill a mosquito. – isedev Oct 03 '14 at 14:30
  • @isedev That is unlikely to matter that much in the OP case but my point is that due to the way it works, `truss` is more of a sledgehammer than `dtrace`... – jlliagre Oct 03 '14 at 16:10
2

A very much more verbose (at least by default) option is to use something like strace for this.

strace -f -o trace.out script.sh

will give you huge amounts of information about what the script is doing. For your specific usage you will likely want to limit the output a bit with the -e trace=.... option to control which system calls are traced.

Use truss instead of strace on Solaris. Use dtruss on OS X (I believe). With appropriate command line argument changes as well.

Etan Reisner
  • 77,877
  • 8
  • 106
  • 148
  • 1
    Or `truss` on Solaris. – isedev Oct 01 '14 at 15:20
  • This would be perfect if the script wasn't triggered from an application side process - I will certainly use this in the future for other tracing needs – Huskie69 Oct 03 '14 at 08:07
  • If you can control the application you can get it to run that. If not, but you can control the script contents, you could always have the script launch `strace`/etc. on itself (using `-p $$` or similar). – Etan Reisner Oct 03 '14 at 11:34