为什么strace忽略我的rm别名?


8

alias有一套rm命令。如果我运行alias命令,这就是我得到的输出。

alias rm='rm -i'

现在,当我运行rm命令时,它可以按预期运行。

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

现在,我正在学习执行命令时正在调用的系统调用。为此,我strace这里了解了命令,该命令列出了我在执行某些命令时正在调用的文件。命令如下。

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

该命令工作正常,只是它会忽略为该rm命令准备的别名。它删除文件而不会提示用户。

那么,是否strace忽略这样的别名?如果是这样,为什么呢?

编辑:

不知道,这是否有帮助,但type -a rm输出为:

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

那么,是否考虑/bin/rm这种情况,这就是为什么在删除之前不提示用户的原因?


3
strace不会忽略别名,因为这首先意味着要忽略的东西。别名是外壳程序的功能。strace是一个不同的程序,并且strace别名的概念不存在,因此没有什么可忽略的。内核提供的用于执行程序的API也没有别名的概念,因此即使它愿意,shell也无法告诉strace别名。
kasperd 2014年

1
如果要strace使用别名,则必须strace使用实现别名的外壳程序。您可以采用几种方法来执行此操作:strace -p $$ &strace bashstrace sh -c 'rm ramesh'(最后一个也将忽略别名,但出于完全不同的原因。)
kasperd 2014年

Answers:


20

stracerm -i由于以下原因而无法运行:

echo rm

不输出rm -i

别名是少数几个shell的功能,当在命令位置找到某些字符串时,它们会自动被另一个字符串替换。

在:

alias foo='whatever'
foo xxx

外壳将其扩展为:

whatever xxx

然后进行另一轮解释,在这种情况下导致执行whatever命令。

仅当在命令位置找到别名(作为命令行的第一个单词)时,别名才会扩展。

zsh支持全局别名。

您可以这样做:

alias -g rm='rm -i'

但是您不想要,因为那意味着:

echo rm

rm -i例如将输出。


8

strace使用PATH环境变量来定位要跟踪的程序,而不是通过外壳执行该程序(这会使输出混乱)。Shell别名不是程序,而是Shell的功能,因此将其strace忽略。

运行strace strace rm颇具启发性,并且有趣地是递归的。


5

别名是Shell的功能。但是,strace直接执行命令(execve可能使用),这不涉及外壳程序。(如果strace通过外壳执行给定的命令,那么strace的输出将包含所有外壳执行syscall,而不只是感兴趣的进程中的系统调用。)

此外,当您运行时strace rm ramesh,交互式外壳程序不会尝试将您的别名替换为strace的参数,因为这会使所有人感到困惑。Shell仅扩展出现在命令行第一位置的别名。


2

strace的用法,execve c function例如find command,但是find uses exec function您不能使用aliasesbuilt-in shell command等等。

你所要做的:

strace /bin/rm -i ramesh

2

如果您定义了StéphaneChazelas的答案,

alias strace="strace "

(末尾有空格),然后执行命令

strace rm ramesh

被处理为

strace rm -i ramesh

但是,即使这仅适用于后面的第一个单词strace,因此也不适用于您的示例(您可以在其中进行选择)。  但是,如果您定义

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

然后

my_strace rm ramesh

被处理为

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

2

这里没有别名

假设我们有别名定义alias rm='rm -i'我们~/.bashrc。别名添加了删除每个文件之前的提示选项:

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

strace不使用别名不是错:
与别名无关。

在命令中

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

单词rm./file现在仅是strace的参数-外壳程序无法扩展别名rm,因为它不知道strace稍后会将这些参数用作命令。

通常,命令别名只能在可以使用命令的地方使用。

别名是外壳程序的功能,并且strace从命令行调用命令时根本不使用外壳程序。而是使用exec()它自己的命令行中的命令和参数。

在中strace,将使用类似于的命令来调用该命令exec("rm", "file"),并将在PATH中exec()找到/bin/rm-无需使用shell。

显式外壳

现在,为什么不在strace命令中包含外壳程序呢?

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

嗯...那没用。rm只是删除了文件,没有-i提示。

交互式别名

别名通常仅在交互式Shell(终端中的实际命令行)中启用。
使用我们的示例别名,很容易理解为什么这样:如果将rm -i别名扩展到shell脚本中,它们将首先挂起,rm没有人按下y

别名由shell选项控制expand_aliases。我们可以使用设置选项bash +O expand_aliases -c ...。但这还不够,因为非交互式外壳也不会读取~/.bashrc。这意味着,我们的别名不仅会被该选项关闭,甚至不会被定义。

假装是互动的

处理这两部分的简单方法是使用命令行选项-i,使外壳假装它是交互式的:

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

最后,使用了-i别名!

请注意-i,即使您希望使用别名,通常也不会使用运行带有该选项的shell 进行脚本编写。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.