6

I'm trying to check whether the current shell session is running within a su login session.

What's the best way to test this condition?

Andrew Vit
  • 228
  • 2
  • 6

3 Answers3

7

look into the logname command. logname will print the username of the user who logged into the controlling terminal as provided by the utmp log.

tk-mbp:~ tkennedy$ id -g -rn
staff
tk-mbp:~ tkennedy$ id -u -rn
tkennedy
tk-mbp:~ tkennedy$ logname
tkennedy
tk-mbp:~ tkennedy$ su -
Password:
tk-mbp:~ root# id -g -rn
wheel
tk-mbp:~ root# id -u -rn
root
tk-mbp:~ root# logname
tkennedy

This example if from Mac OS X, so the use of the id command may differ to other OSes, however, the use of logname is consistent between Mac OS X, Linux, and Solaris, which are all the OSes I have available to night to test with.

By using logname, you can assume that if the user returned by the id command is not the same as the user returned by logname, then the current shell session is being run under su, or sudo, or some other tool that allows for privilege change in a shell.

Tim Kennedy
  • 19,697
  • These are standard environment variables as well, so [[ if $LOGNAME != $USER ]] works perfectly. – Andrew Vit Nov 07 '11 at 17:12
  • 1
    @AndrewVit: I thought so too, but when I execute echo "$USER / $LOGNAME / $(logname)" inside sudo -i on my Mac OS X, I get: root / root / janmoesen. – janmoesen Nov 08 '11 at 08:01
4

If you want to test whether the current shell was executed by su:

[ "$(ps -o comm= $PPID)" = "su" ]

If you want to test whether the user called su since logging in, then on many (but not all) systems you can compare LOGNAME (normally set at the initial login) with USER or id -un (which identifies the current user). Note that LOGNAME is trivially spoofable (it's an environment variable). But then, so are other solutions (for example ln -s /bin/su ~/sh; ~/sh will hide the su from any solution based on process names).

  • My question was just for a shell prompt so I don't need anything super robust. That test works well. Nice trick using the -o option to hide the header! – Andrew Vit Nov 08 '11 at 20:17
0

Here's one solution I wired up:

pstree -p $$ | 
grep -oP '[r]oot su .*(\w+)' |
sed -n -E 's/.* ([[:alnum:]]+)$/\1/p'`

pstree with the -p flag lists the ancestry tree of the current shell process PID ($$)

grep finds lines containing "root su" (I'm using the [r] trick to avoid returning the grep process itself)

sed cleans up the result and prints just the current username at the end of the line. (It would be more helpful if it would print the user of the parent process though.)

Andrew Vit
  • 228
  • 2
  • 6