I have a bash function (or alias), for instance function install() {sudo apt-get install $@}
. When running the command install dicelab
, what I expect will actually be run is sudo apt-get install dicelab
. Where can I see what was actually run by the shell? I would like to make sure that my more complicated aliases are working as expected.
4 Answers
Use set -x
in the shell.
$ alias hello='echo hello world!'
$ hello
hello world!
$ set -x
$ hello
+ echo hello world!
hello world!
Using set -x
turns on the xtrace
shell option (set +x
turns it off) and should work in all Bourne-like shells, like bash
, dash
ksh93
, pdksh
and zsh
. This prompts the shell to display the command that gets executed after alias expansions and variable expansions etc. has been performed.
The output will be on the standard error stream of the shell (just like the ordinary prompt) so it will not interfere with redirections of standard output, and it will be preceded by a prompt as defined by the PS4
shell variable (often +␣
by default).
Example with a few functions:
$ world () { echo "world"; }
$ hello () { echo "hello"; }
$ helloworld () { printf '%s %s!\n' "$(hello)" "$(world)"; }
$ helloworld
hello world!
$ set -x
$ helloworld
+ helloworld
++ hello
++ echo hello
++ world
++ echo world
+ printf '%s %s!\n' hello world
hello world!
With your specific example (with syntax corrected and added quotes):
$ install () { sudo apt-get install "$@"; }
$ set -x
$ install dicelab
+ install dicelab
+ sudo apt-get install dicelab
bash: sudo: command not found
(I don't use or have sudo
on my system, so that error is expected.)
Note that there is a common utility already called install
, so naming your function something else (aptin
?) may be needed if you at some point want to use that utility.
Note that the trace output is debugging output. It is a representation of what the shell is doing while executing your command. The output that you see on the screen may not be suitable for shell input.
Also note that I was using bash
above. Other shells may have another default trace prompt (zsh
incorporates the string zsh
and the current command's history number, for example) or may not "stack" the prompts up like bash
does for nested calls.
I'm running I used to run with set -x
in all my interactive shells by default. It's nice to see what actually got executed... but I've noticed that programmable tab completion etc. may cause unwanted trace output in some shells, and some shells are a bit verbose in their default trace output (e.g. zsh
).
You could use shell-expand-line
, which is bound to
Control-Alt-e by default:
$ bind -p | grep shell-expand-line
"\e\C-e": shell-expand-line
Among other things, it will replace aliases in the current line with their definition so you can see a command you're still going to run. Example:
$ install dicelab # now press C-Alt-e
$ sudo apt-get install dicelab # the above line will be replaced with this
-
this is a nice feature. do you know if zsh has an equivalent command to
shell-expand-line
? May 4, 2017 at 8:16 -
Sorry, I don't because I don't use
zsh
. But some people have come up with their own ideas: wiki.math.cmu.edu/iki/wiki/tips/20140625-zsh-expand-alias.html May 4, 2017 at 8:32 -
@the_velour_fog, see Resolve all aliases in a zsh command line May 5, 2017 at 13:33
Use builtin command type
to see an alias or a function definition you are about to run
This solution doesn't require running the command
$ type ls
ls is aliased to `ls --color=auto -p'
$ type -a ls
ls is aliased to `ls --color=auto -p'
ls is /bin/ls
From help type
: -a
display all locations containing an executable named NAME; includes aliases, builtins, and functions, if and only if the `-p' option is not also used
$ function hello() { echo hello; } # define function
$ type hello
hello is a function
hello ()
{
echo hello
}
A simple approach for a specific alias is to try ps.
If you do ps -f, you will see the actual command adjacent to the process, not the alias name. You can verify that by defining the following alias:
alias doSleep="sleep 100"
then do
ps -f | grep "sleep"
and you will see
username 14303 2409 0 15:16 pts/0 00:00:00 sleep 100
Unfortunately, the history command only shows the alias, so you couldn't use history to verify that the actual command ran; you could only search for the alias label in that case.
-
If you ran it with
doSleep&
and/or ^Z-ed out (which are the only ways you can see it inps
on the same terminal) thenjobs
(orjobs %id
if you know/remember or guess the id) shows the expansion of an alias -- but not the contents of a function. which is the actual example in the question. Sep 23, 2022 at 4:55
$@
part of your alias? Remember that aliases don't really support arguments, that will expand to the positional parameters (if any) of the context calling the alias. The usual way of runningsomealias some args
works just by expanding the alias and leaving the arguments to follow it. If you actually want to be able to access the arguments, use a function, and quote the"$@"
"$@"
, arguments with whitespace or glob characters will burn otherwise.