0

Consider the following Bash alias:

alias su='sudo -s'

The problem one might encounter is running it (that alias) while already root.

Demo:

$ su
[sudo] password for vlastimil:                
# su
# su
# 
exit
# 
exit
# 
exit
$ 

Is there a way to avoid the nested shell sessions?

Important note: I am using the same alias file for my user and root, not separate.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
Vlastimil Burián
  • 27,586
  • 56
  • 179
  • 309

2 Answers2

3

su and sudo -s are different commands with different APIs and semantic and behaviour, you shouldn't alias one to the other.

Here it seems you want a command that starts root's login shell as root via sudo but only when invoked from a non-privileged shell, so I would write a script called rootshell for instance as:

#! /bin/sh -

die() {
  printf >&2 '%s\n' "$@"
  exit 1
}

[ "$#" -eq 0 ] || die "Usage: $0

Starts a root shell, no argument accepted."

[ "$(id -u)" -eq 0 ] && die "You're already superuser!"

exec sudo -s

Or if you don't want to make a script, make it a shell function by wrapping that code as rootshell() (<that-code>) to add in your shell rc file (change $0 to the name of the function as not all shells put the function name in $0).

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • I can always do `\su` if I want, so what's the point? – Vlastimil Burián Nov 20 '22 at 09:17
  • 2
    @VlastimilBurián That's similar to saying "I called my command that recursively finds PDF file `ls`. I can always do `\ls` if I just want to list files". The point is that you have two very different commands and you're calling one by the name of another. – Kusalananda Nov 20 '22 at 10:14
0

My solution follows:

alias su='[ $(id -u) -ne 0 ] && sudo -s'

  • POSIX compatible, which means if you copy-paste it to dash or I suppose almost any other shell supporting aliases, you should get the same behavior.

  • That is also why I avoided EUID and direct value comparison altogether.


Demo:

$ su
[sudo] password for vlastimil:                
# su
# su
# su
# 
exit
$ 

Considering I use sudo -s, I attach its comparison with sudo -s vs other variants.

Vlastimil Burián
  • 27,586
  • 56
  • 179
  • 309
  • Wouldn't it be simpler to do `alias su=:` for the root user? You have to define the alias for the root user anyway, so might as well alias it to a no-op directly since you already know it's for root – muru Nov 20 '22 at 06:22
  • @muru I forgot to say in the question something important. But you are correct in your way! – Vlastimil Burián Nov 20 '22 at 06:46
  • Ah, but my point still stands - instead of doing the check at runtime, do the check at definition time: `if [ $(id -u) -eq 0 ]; then alias su=: ; else alias su='sudo -s'; fi` – muru Nov 20 '22 at 07:00
  • @muru Very good! I missed it :) – Vlastimil Burián Nov 20 '22 at 07:08
  • 1
    aliases are for csh users. Bourne-like shells have functions which are much more appropriate if you want to create a new command without having to write a script. aliases are just text replaced with other text before shell syntax interpretation. So here, `some-cmd || su -c other-cmd` for instance won't do what you want because that's expanded to `some-cmd || [ $(id -u) -ne 0 ] && sudo -s -c other-cmd`. – Stéphane Chazelas Nov 20 '22 at 10:45