1

I have a bash script foocaller, which calls a ruby script foo:

foocaller

/path/to/foo

Within foo, I want to get the path of foocaller. Following this suggestion, I put the following code to do that:

foo

#!/usr/bin/env ruby
puts File.read("/proc/#{Process.ppid}/cmdline")

When I run:

$ bash foocaller

then I get the desired:

bash^@/path/to/foocaller

but when I directly call foocaller:

$ foocaller

then I get this:

/bin/bash^@--noediting^@-i

which does not show the path to foocaller. How can I get the path to foocaller by directly calling foocaller without bash?

sawa
  • 872

1 Answers1

3

Many shells optimise the last command in a script by executing the command in the same process:

$ sh -c 'ps
ps'
  PID TTY          TIME CMD
32673 pts/3    00:00:00 zsh
32696 pts/3    00:00:00 sh
32697 pts/3    00:00:00 ps
  PID TTY          TIME CMD
32673 pts/3    00:00:00 zsh
32696 pts/3    00:00:00 ps

See how the second ps was executed in the process that initially ran sh (32696), and then its parent is the sh's parent (in my case here, zsh my interactive shell).

You can avoid that by adding an exit line:

#! /bin/sh -
foo
exit

sh cannot execute foo in the same process because, it still has more to interpret after foo has finished. So it will instead run foo in another process and wait for it. And then run exit (which will exit the script with the same exit status as that of foo).

Now, that's not very optimal, as you could have saved a process here.

A better way to have foo know about the path of foocaller could be to tell it:

#! /bin/sh -
CALLER=$0 foo

Then foo can query the CALLER environment variable to get the path of its caller (import os;print(os.environ["CALLER"]) in python)