1

I am running Ubuntu 22 ( "22.04.4 LTS (Jammy Jellyfish)")

I understand that in any linux shell script the symbol $$ denotes the pid of the process running that script

I have a shell script that needs to ensure it runs under bourne so it determines which shell it is being run under.That determination of shell is needed because script has lot of non portable bourne shell specific code.

So in order to ensure that this script runs under bourne, in addition to a shebang I decided to add some more saftey check to determine which shell is running the script. That is because some users tend to specify a shell explicitly thus overriding shebang

Review following code snippet from my shell script that makes a determination of the shell under which script is being run. This uses $$ and finds the name of process that has PID=$$ ; this runs fine if there is NO shebang at begining of script

runshell=`ps -p $$ |grep -v PID| awk '{print $4}'`
if [ $runshell != "sh" ]
then
   echo " shell is $runshell"; exit 99;
   echo "You must run this in bourne shell. Exiting"
   exit 99;
fi
echo "Running in bourne shell. "
# rest of code that needs to run in bourne shell 

As far as there is no shebang, above script runs perfectly fine ( the variable "runshell" has the value of shell that runs the script) .

However if I introduce shebang as follows, then the name of process having pid $$ turns out to be the script name typed at command line . So in the below snippet the vaiable 'runshell' gets value = .

#!/bin/sh
runshell=`ps -p $$ |grep -v PID| awk '{print $4}'`
if [ $runshell != "sh" ]
then
   echo " shell is $runshell"; exit 99;
   echo "You must run this in bourne shell. Exiting ";
   exit 99;
fi
# rest of code that needs to run in bourne shell

when I run this script as "./script.sh " then the described problem happens

However if I run it specifying a shell as "sh script.sh" then it detects the shell correctly

so questions

  1. Why should a shebang influence value of $$ (and hence the name of proces with PID $$) ?
  2. And if I need to retain the shebang how do I make determination of shell under which the script is running ?

Thanks for your help

  • 2
    Please edit the question and add the version of Ubuntu you are running. – David DE Sep 12 '24 at 08:55
  • Do note that different OSes have different defaults; Debian & Ubuntu haven't used Shell; with the shell being used depending on how the code is executed (dash or bash being selected); see https://wiki.debian.org/Shell or https://wiki.ubuntu.com/DashAsBinSh ... You mention only Linux, where there are differences; thus why using shebangs is always recommended. – guiverc Sep 12 '24 at 09:04
  • 1
    Note that checking the process the way you're doing it isn't safe either; just try sh script.sh and you'll see that the "shell" running the script is Sh, however Sh (which resolves to /usr/bin/sh) is a symlink to /usr/bin/dash. So one could "spoof" the running shell by symlinking, say, fooshell to /usr/bin/bash and invoke the script with ./fooshell script.sh (having the script thinking fooshell is running the script while in fact Bash is running the script). – kos Sep 12 '24 at 09:50
  • https://askubuntu.com/questions/590899/how-do-i-check-which-shell-i-am-using/590901#590901 – kos Sep 12 '24 at 10:20

1 Answers1

0

I found a workaround.
If you examine the process list from within script using full format listing (ps -ef) you can see that the full format listing does give you an indication of shell used. This worked in all cases that I looked at i.e with or without shebang and using the default shell or specifying another shell ( bourne or otherwise). So for now I switched to using output pf ps -f to determine the shell instead of $$. See below

$sh test.sh
UID          PID    PPID  C STIME TTY          TIME CMD
myuser      74162   73468  0 09:53 pts/1    00:00:00 sh test.sh

$./test.sh UID PID PPID C STIME TTY TIME CMD root 74148 73468 0 09:53 pts/1 00:00:00 /bin/sh

$bash test.sh UID PID PPID C STIME TTY TIME CMD root 74572 73468 0 10:02 pts/1 00:00:00 bash test.sh

so my working snippet using a derivative of full format list (instead of relying on $$) looks like below

#!/bin/sh
runshell=$(ps -ef |grep $0 |grep -v grep | awk '{print $8}'| sort -u)
if [ "$runshell" != "sh" ] && [ "$runshell" != "/bin/sh" ]
then 
    echo " you are NOT using bourne shell - exiting"
    exit 99
fi
echo " you are using bourne shell "
# run bourne specific code 
  • 1
    Now if I symlinked sh (/usr/bin/sh) to, say, fooshell in the current working directory, and I ran ./fooshell script.sh this would fail thinking "it's not Bourne shell running the script", while in fact it's sh running the script (and by the way: sh is not the Bourne shell). What's the purpose in trying to identify the running shell exactly? The only reliable way I personally can think of to unambiguosly determine the running shell is to check for the presence of shell-specific features. Anything else (that I can think of) can be spoofed: process name, env variables etc. – kos Sep 15 '24 at 00:51
  • Hi kos, I have a reason to determine the shell . I need to impose a specific shell and prevent inadvertant running script under another ( likely incompatible) shell . A shebang can be overwridden by explicily specifying shell on command line. – Yogesh Devi Nov 22 '24 at 06:41