34

I am running Ubuntu 10.04 and I use upstart for daemon management. My enterprise application is run as a daemon and must be run as root because of various privileges. E.g.:

sudo start my-application-long-ID
sudo stop my-application-long-ID
etc

I would like to introduce an alias to abbreviate these commands as something like:

alias startapp='sudo start my-application-long-ID'

and run it as startapp and that works but I would prefer to not have sudo in the alias.

alias startapp='start my-application-long-ID'

does not when run using sudo startapp, returning sudo: startapp: command not found.

However, when I added the alias:

alias sudo='sudo '

sudo startapp now works but I am still curious why sudo ignores aliases.

3

4 Answers 4

56

I see the below information from here.

When using sudo, use alias expansion (otherwise sudo ignores your aliases)

alias sudo='sudo '

The reason why it doesn't work is explained here.

Bash only checks the first word of a command for an alias, any words after that are not checked. That means in a command like sudo ll, only the first word (sudo) is checked by bash for an alias, ll is ignored. We can tell bash to check the next word after the alias (i.e sudo) by adding a space to the end of the alias value.

0
9

Aliases and functions are defined in a shell. Sudo is an external program. So sudo doesn't see aliases, functions or shell builtins, only external commands.

Aliases are meant to be alternate command names, so shells only expand them in command position, not when they're arguments to commands. Zsh supports global aliases, which are expanded anywhere on the command line, and best use sparingly since there is a risk of accidentally expanding them even in contexts where the alias doesn't make sense.

You can tell sudo to invoke a shell: sudo sh -c '…shell command here…'. Your usual aliases won't be available inside that shell command, however, since they're normally stored in a file such as ~/.bashrc or ~/.zshrc which is only read by interactive shells.

alias sudo='sudo ', as proposed by Ramesh, causes the shell to expand aliases after sudo.

3
  • 1
    Does the alias sudo='sudo ' work for ZSH as well? Commented Sep 13, 2016 at 17:44
  • 3
    @CMCDragonkai Yes Commented Sep 13, 2016 at 17:48
  • Well, it no longer works with zsh ... Commented Jul 5 at 8:46
4

A solution for zsh users

In both bash and zsh, ending an alias with a space will cause the shell to alias-expand the next word. This allows something like the following to alias expand myalias

alias 'sudo=sudo '
sudo myalias

Unfortunately this falls apart when you have more then one word in your alias (like sudo -u someone. However you can abuse the zsh "global aliases" feature to manually expand aliases anywhere in the command.

alias -g '$= '

This creates a global alias called $ (you can use any word you want) which ends in a space. This causes zsh to expand the next word as a regular command alias. Since the alias expands to whitespace it won't be treated as an argument. This allows the following to work.

% alias myalias=echo
% sudo -u someone myalias foo
sudo: myalias: command not found
% sudo -u someone $ myalias foo
foo

You can even use $ multiple times on one command line if you have complicated command nesting. I've found this useful enough that it has a permanent place in my zshrc, however the alias is simple enough to define when you need to use it.

1

I just gave an an alternative answer here without redefining sudo with an alias.

In your case it would be:

type -a startapp | grep -o -P "(?<=\`).*(?=')" | xargs sudo 

All in one line, no extra shells, no alias redefinitions. ;-)

3
  • Oh wait a minute - I get it - you're using xargs to strip the quotes, and grep to strip the leading =. Kinda clever, but probably unnecessary. eval "sudo $(alias aliasname | cut -d= -f2-)" is likely better - xargs won't always handle the quotes correctly, and there could be more than one = in there.
    – mikeserv
    Commented Feb 15, 2015 at 20:37
  • @mikeserv I am sorry you didn't get it ;-) xargs do not strips the quotes. It is grep who takes the resolved command from between the quotes. You know type -a alias_name returns something like alias_name is aliased to command_within_quotes. By the way I have tried your command and didn't work on my ubuntu :-(. Is it the return of type -a different between linux versions? (i doubt it). Commented Feb 16, 2015 at 8:22
  • I know what type does - in bash. You understand though, that the quotes are doubled right? Have you tried it with an alias that contained single quotes? Anyway, you're right about my thing not working - you need either eval "sudo sh -c "$(... or eval "'sudo $(alias alias_name| cut -d\' -f2-)". The thing is aliases are basically prearranged evals - the alias utility is spec'd to output their contents so that it can be safely reinput to the shell. I guess your xargs is implemented then to flatten the whitespace? Just be careful with that, ok?
    – mikeserv
    Commented Feb 16, 2015 at 9:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .