31

I have an alias that passes in some parameters to a tool that I use often. Sometimes I run as myself, sometimes under sudo. Unfortunately, of course, sudo doesn't recognise the alias.

Does anyone have a hint on how to pass the alias through?

In this case, I have a bunch of options for perl when I'm debugging:

alias pd='perl -Ilib -I/home/myuser/lib -d'

Sometimes, I have to debug my tools as root, so, instead of running:

pd ./mytool --some params

I need to run it under sudo. I've tried many ways:

sudo eval $(alias pd)\; pd ./mytool --some params
sudo $(alias pd)\; pd ./mytool --some params
sudo bash -c "$(alias pd)\; pd ./mytool --some params"
sudo bash -c "$(alias pd); pd ./mytool --some params"
sudo bash -c eval\ "$(alias pd)\; pd ./mytool --some params"
sudo bash -c eval\ "'$(alias pd)\; pd ./mytool --some params'"

I was hoping for a nice, concise way to ensure that my current pd alias was fully used (in case I need to tweak it later), though some of my attempts weren't concise at all. My last resort is to put it into a shell script and put that somewhere that sudo will be able to find. But aliases are soooo handy sometimes, so it is a last resort.

Tanktalus
  • 451
  • 1
  • 4
  • 11

12 Answers12

52

A very elegant solution can be found in the Archlinux-Wiki:

alias sudo='sudo '
# whitespace ---^

works to pass all aliases to sudo.

Source: http://wiki.archlinux.org/index.php/Sudo#Passing_aliases

Slizzered
  • 774
  • 5
  • 16
  • 17
    This is a great trick! For the curious, the explanation from the alias section in the bash manpage: `A trailing space in value causes the next word to be checked for alias substitution when the alias is expanded.` – Russell Davis Nov 23 '11 at 19:36
  • 1
    This should really be the accepted answer. – Adrian Frühwirth Oct 11 '13 at 07:39
  • It is a shame that this does not work for functions. – Ciro Santilli OurBigBook.com Aug 09 '15 at 19:46
  • 2
    __Note:__ Supposing you DO need to pass an __option__ to `sudo` again, while wanting to keep that `sudo`-passthrough trick at the same time. Even this can be done: to use options again, use `\sudo`. The backslash will *override* the alias. (Many don't seem to know about that). This way, you can (*danger!*) even remove files without *any* warning, overriding the `alias rm='rm -i'` commonly specified in `.bash-aliases`, simply by typing `\rm file-to-delete`. – syntaxerror Jan 29 '16 at 16:16
12

I'm not real clear on what you're trying to do. I can see two ways:

The Right Way

alias pd='sudo perl -Ilib -I/home/myuser/lib -d'

Then executing pd ./mytool will execute your debugging command as root but still preserve the benefits of sudo (audit trail, not operating out of a root shell).

Example:

insyte$ alias sid='sudo id'
insyte$ sid
uid=0(root) gid=0(root) groups=0(root)

The Easy Way

Add the aliases to root's .bashrc and use sudo -i whenever you sudo to root.

root# echo 'alias fb="echo foo bar"' >> /root/.bashrc
root# exit
exit
insyte$ sudo -i
root# fb
foo bar
Insyte
  • 9,314
  • 2
  • 27
  • 45
  • It's not clear to me what all the debate is about. Insyte's "Right Way" seems easiest, and in a departure from the norm, also seems most intuitive. – Seamus Dec 08 '20 at 01:19
4

from http://www.shellperson.net/using-sudo-with-an-alias/

alias sudo='sudo '
KitsuneYMG
  • 181
  • 5
4

I wish I could mark two answers as "correct". Combining the Right Way from Insyte's, um, insightful post, with the awk (or cut) solution from Bill Weiss, I've come up with this:

alias spd="sudo $(alias pd | cut -d\' -f2)"

Now I'll just go and put this into a shell function in my .bashrc or something, and then create "s" versions of all my aliases that I desire to run as root.

Update: slight modification of Dennis Williamson's simplistic function to make it a bit easier to use:

 salias()
 {
   local a c
   a=$(echo "$1" | cut -f1 -d=)
   c=$(echo "$1" | cut -f2- -d=)
   alias $a="$c"
   alias s$a="sudo $c"
 }

This means I just have to put "s" in front of the entire command. Instead of:

alias pd='perl -Ilib -I/home/myuser/lib -d'

I just add the s in the front.

salias pd='perl -Ilib -I/home/myuser/lib -d'

And I'm done. Sure, the computer does a bit more work, but that's what a computer is for. :-)

Thanks!

Tanktalus
  • 451
  • 1
  • 4
  • 11
4

Just have two aliases and use a variable

I don't see the reason for using awk or cut unless it's to only have the core alias defined once in order to make it easier to modify. If that's the case, then this works:

# ... in .bashrc ...
pd='perl -Ilib -I/home/myuser/lib -d'
alias pd="$pd"
alias spd="sudo $pd"

Here's a simplistic function to make alias pairs such as the one above:

mkap () {
    alias $1=$2
    alias s$1="sudo $2"
}

To use:

mkap pd 'perl -Ilib -I/home/myuser/lib -d'
mkap ct 'cat'

Now you have pd and spd plus ct and sct.

$ ct /etc/shadow
cat: /etc/shadow: Permission denied
$ sct /etc/shadow
[sudo] password for dennis:
root:[censored]...
$ alias
alias ct='cat'
alias pd='perl -Ilib -I/home/myuser/lib -d'
alias sct='sudo cat'
alias spd='sudo perl -Ilib -I/home/myuser/lib -d'
Dennis Williamson
  • 60,515
  • 14
  • 113
  • 148
3

As posted a few times, do in '.bashrc':

alias sudo='sudo '

The reason why is explained in 'man bash' and 'help alias':

alias: alias [-p] [name[=value] ... ] Define or display aliases.

Without arguments, `alias' prints the list of aliases in the reusable
form `alias NAME=VALUE' on standard output.

Otherwise, an alias is defined for each NAME whose VALUE is given.
**A trailing space in VALUE causes the next word to be checked for
alias substitution when the alias is expanded.**
sixerjman
  • 31
  • 1
3

Wouldn't it be easier to simply hack out a script that includes your options, then place it somewhere in one of the folders that is the path for regular account and root? It really wouldn't take much of a script.

#!/bin/bash
exec perl -Ilib -I/home/myuser/lib -d $*
Zoredache
  • 128,755
  • 40
  • 271
  • 413
  • It actually has to be "$@" instead of $*, and that's part of the reason I generally try to avoid it. ;-) It works, it just wastes a bunch of disk space relative to what it contains. – Tanktalus Sep 01 '09 at 21:22
3

This is rough, but it works here:

houdini@clanspum:~/ > alias fb
fb='echo foo bar'
houdini@clanspum:~/ > alias fb | awk -F\' '{print $2}'
echo foo bar
houdini@clanspum:~/ > sudo sh -c "$(alias fb | awk -F\' '{print $2}')"
foo bar
houdini@clanspum:~/ > sudo sh -c "$(alias fb | awk -F\' '{print $2}') a b c"
foo bar a b c
houdini@clanspum:~/ > fb
foo bar
houdini@clanspum:~/ > fb a b c
foo bar a b c
Bill Weiss
  • 10,782
  • 3
  • 37
  • 65
  • I pasted an incomplete solution here, then edited to fix. The current one is right. A free upvote to the first person to comment explaining what's going on here :) – Bill Weiss Sep 01 '09 at 22:02
  • I was hoping for a simpler way than awk, but hope != reality sometimes ;-) Apparently, "cut -f2 -d\'" would work just as well as awk, and be that tiny bit shorter. – Tanktalus Sep 01 '09 at 22:05
  • Yeah, cut would work, I always forget about it. – Bill Weiss Sep 01 '09 at 22:07
3

Add a "sudo " prefix to selected aliases AND commands from within your ~/.bashrc like so:

#a regular alias
alias pd='perl -Ilib -I/home/myuser/lib -d'

#sudofy (command id, alias pd - add others to this list)
for cmd in id pd;
      do alias "s$cmd"="sudo $cmd";
done;
1

I don't know if it's the wisest thing to do on a production box but locally I use

alias sudo="sudo -E"

The -E (preserve environment) option will override the env_reset option in sudoers(5)). It is only available when either the matching command has the SETENV tag or the setenv option is set in sudoers(5).

1

You want something like this:

(alias; echo "exec < /dev/tty") | sudo bash  -i
geocar
  • 2,307
  • 14
  • 10
  • I might be wrong, but ISTR that `bash -i` (i = interactive) is v4.0 only. So on an older server that still got `bash` v3 running, this would most likely fail. But prove me wrong, anyone, go ahead ;) – syntaxerror Jan 29 '16 at 16:35
  • @syntaxerror - You remember wrong. `-i` is Bourne shell, see: http://pubs.opengroup.org/onlinepubs/009695399/utilities/sh.html – geocar Jan 29 '16 at 17:57
  • Wow, didn't expect to get a reply so soon for a 6+-year-old post...Why yes, I might have confused it with `#!/bin/bash -i` after the shebang, which is apparently not the same (?). To cut a long story short, using `history` in a `bash` script (and not on the "live" command line) *will* require the `-i` option, which I was unable to get working on a server with "only" `bash` v3 installed. And that's a fact. – syntaxerror Jan 29 '16 at 18:18
-1

Can you add the alias to root's .bashrc or just execute .bashrc through sudo before your command?

sudo (. ~yourlogin/.bashrc; pd ./mytool --some params)
Robert Swisher
  • 1,147
  • 7
  • 14
  • 1
    Um, this didn't even almost work, either. It's actually fairly close to some of the things I tried above, but is further away from actual shell/sudo syntax. – Tanktalus Sep 01 '09 at 21:34