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にもエイリアスの概念がないため、シェルがエイリアスについてstraceに通知する方法はありません。
kasperd 2014

1
あなたがしたい場合はstrace、エイリアス、あなたがしなければならないstraceエイリアスを実装し、シェル、。それを行うために取ることができるいくつかのアプローチがあります:strace -p $$ &or strace bashまたはstrace sh -c 'rm ramesh'(最後のものもエイリアスを無視しますが、まったく異なる理由で)
kasperd

回答:


20

stracerm -i同じ理由で実行されません:

echo rm

出力しませんrm -i

エイリアスはいくつかのシェルの機能で、コマンドの位置にある文字列を自動的に別の文字列に置き換えることができます。

に:

alias foo='whatever'
foo xxx

シェルはそれを次のように拡張します。

whatever xxx

そして、その場合、whateverコマンドの実行につながる、別のラウンドの解釈を受けます。

エイリアスは、コマンド位置(コマンドラインの最初の単語として)にある場合にのみ展開されます。

zshグローバルエイリアスをサポートしています。

あなたはできる:

alias -g rm='rm -i'

しかし、次のことを意味するので、そうしたくないでしょう。

echo rm

rm -iたとえば出力します。


8

stracePATHシェルを介してプログラムを実行するのではなく、環境変数を使用して、トレースするプログラムを見つけます(出力が乱雑になります)。シェルエイリアスはプログラムではなく、シェルの機能であるため、strace無視されます。

走ることstrace strace rmはかなり啓発的であり、興味深いことに再帰的です。


5

エイリアスはシェルの機能です。ただし、straceはコマンドを直接(execveおそらくを使用して)実行します。これにはシェルは関与しません。(straceがシェルを介して特定のコマンドを実行した場合、straceの出力には、対象のプロセスからのシェルコールだけでなく、すべてのシェル実行syscallが含まれます。)

さらに、を実行するstrace rm rameshと、対話型シェルはstraceの引数でエイリアスを置き換えようとしません。これは、誰にとっても非常に混乱するためです。シェルは、コマンドラインの最初の位置に表示されるエイリアスのみを展開します。


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")、とexec()あります/bin/rmPATHに-シェルを使用せずに。

明示的なシェル

さて、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です。

インタラクティブなエイリアス

エイリアスは通常、インタラクティブシェル、つまりターミナルの実際のコマンドラインでのみ有効です。
私たちのエイリアスの例を使用すると、それが理にかなっている理由を簡単にrm -i理解できます。エイリアスがシェルスクリプト内で展開される場合、それらは最初にハングし、rm誰も押しませんy

エイリアスは、シェルオプションによって制御されます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たとえば、エイリアスを使用できるようにしたい場合でも、スクリプトのオプションを指定して実行しているシェルは通常使用しません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.