8

I have an alias set for my rm command. If I run alias command, this is what I get as output.

alias rm='rm -i'

Now, when I run the rm command it works fine as expected.

rm ramesh
rm: remove regular empty file `ramesh'? y

Now, I was learning on the system calls that are being called when I execute a command. For that I got to know about the strace command from here which lists me the files that are being called when I execute some command. The command is as below.

strace -ff -e trace=file rm ramesh 2>&1 

The command works perfectly fine except that it ignores my aliases that I have in place for my rm command. It deletes the file without prompting the user.

So, does strace ignore aliases like this? If so why is it so?

EDIT:

Not sure, if this has something to do but type -a rm gives me the output as,

rm is aliased to `rm -i'
rm is /bin/rm

So is it considering /bin/rm in this case which is why the user is not prompted before deletion?

  • 3
    strace does not ignore aliases, because that would imply there was something to ignore in the first place. An alias is a feature of the shell. strace is a different program, and inside strace the concept of aliases does not exist, hence there is nothing to ignore. The API provided by the kernel for executing programs does not have a concept of aliases either, so there is no way the shell could tell strace about aliases, even if it wanted to. – kasperd Sep 18 '14 at 9:52
  • 1
    If you want to strace an alias, you have to strace the shell, which implements the alias. There is a few approaches you could take to doing that: strace -p $$ & or strace bash or strace sh -c 'rm ramesh' (the last will also ignore the alias, but for an entirely different reason.) – kasperd Sep 18 '14 at 9:55
20

strace doesn't run rm -i for the same reason as:

echo rm

doesn't output rm -i.

Aliases are a feature of a few shells to allow some strings to automatically be replaced by another when found in command position.

In:

alias foo='whatever'
foo xxx

The shells expands that to:

whatever xxx

and that undergoes another round of interpretation, in that case leading to executing the whatever command.

aliases are only expanded when found in command position (as the first word of a command line).

zsh supports global aliases.

You could do:

alias -g rm='rm -i'

But you wouldn't want to, as that would mean that:

echo rm

would output rm -i for instance.

8

strace uses the PATH environment variable to locate the program to be traced, rather than executing it through the shell (which would clutter up the output). A shell alias isn't a program, it's a feature of the shell, and so strace ignores it.

Running strace strace rm is rather enlightening, as well as being interestingly recursive.

5

An alias is a feature of your shell. However, strace executes the command directly (using execve, probably), which does not involve the shell. (If strace executed the given command through the shell, then the output of strace would contain all of the shell execution syscalls rather than just those from the process of interest.)

Furthermore, when you run strace rm ramesh, the interactive shell does not attempt to substitute your alias in the arguments to strace, because that would be terribly confusing for everybody. The shell only expands aliases that appear in the first position on a command line.

2

strace uses execve c function such as find command,However find uses exec function You can't use aliases, built-in shell command or so on.

You have to do:

strace /bin/rm -i ramesh
2

To build on Stéphane Chazelas’s answer, if you define

alias strace="strace "

(with a space at the end) then the command

strace rm ramesh

will be processed as

strace rm -i ramesh

But even this will work for only the first word after the strace, so it wouldn’t apply directly to your example (where you have intervening options).  But, if you define

alias my_strace="strace -ff -e trace=file "

then

my_strace rm ramesh

will be processed as

strace -ff -e trace=file rm -i ramesh
2

No aliases here

Let's assume we have the alias definition alias rm='rm -i' in our ~/.bashrc. The alias adds the option for prompting before removing each file:

$ touch ./file
$ rm ./file
/bin/rm: remove regular empty file ‘./file’? 

It's not the fault of strace that it did not use the alias:
It has just nothing to do with aliases.

In the command

$ strace -f -e file -o rm.strace rm ./file

The words rm and ./file are just arguments for strace for now - the shell can not expand the alias rm, because it can not know that strace will use these arguments as command later.

In general, command aliases can only be used where commands can be.

Aliases are a feature of the shell, and strace does not use a shell at all when it calls the command from the command line. It uses exec() instead, with the commands and arguments from it's own command line.

Inside of strace, the command will be called with something similar to exec("rm", "file"), and exec() will find /bin/rm in PATH - without using a shell.

Explicit shell

Now, why not include a shell in the strace command?

$ touch ./file
$ strace -f -e file -o rm.strace bash -c 'rm ./file'
$ ls ./file
ls: cannot access ./file: No such file or directory

Hmm... that did not work. rm just deleted the file, without the -i prompt.

Interactive aliases

Aliases are normally only enabled in interactive shells, actual command lines in a terminal.
With our example alias, it's easy to see why that makes sense: If the rm -i alias would be expanded inside shell scripts, they would hang at the first rm with nobody there for pressing y.

Aliases are controlled by the shell option expand_aliases. We could set the option with bash +O expand_aliases -c .... But that's not enough, because the non-interactive shell will also not read ~/.bashrc. That means, our alias is not only switched off by the option, but also not even defined.

Pretending to be interactive

The easy way to handle both parts is to use the command line option -i to make the shell pretend it is interactive:

$ touch ./file
$ strace -f -e file -o rm.strace bash -i -c 'rm ./file'
/bin/rm: remove regular empty file ‘./file’?

Finally, the -i alias was used!

Note that you would not normally use shells running with the -i option for scripting, even if you would want to have your aliases available, for example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.