mengapa strace mengabaikan alias saya untuk rm?

8

Saya memiliki satu aliasset untuk rmperintah saya . Jika saya menjalankan aliasperintah, inilah yang saya dapatkan sebagai output.

alias rm='rm -i'

Sekarang, ketika saya menjalankan rmperintah itu berfungsi dengan baik seperti yang diharapkan.

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

Sekarang, saya sedang belajar tentang pemanggilan sistem yang dipanggil ketika saya menjalankan perintah. Untuk itu saya harus tahu tentang straceperintah dari sini yang mencantumkan saya file yang dipanggil ketika saya menjalankan beberapa perintah. Perintahnya seperti di bawah ini.

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

Perintah berfungsi dengan baik kecuali bahwa itu mengabaikan alias saya yang ada di tempat untuk rmperintah saya . Menghapus file tanpa meminta pengguna.

Jadi, apakah straceabaikan alias seperti ini? Jika demikian mengapa demikian?

EDIT:

Tidak yakin, apakah ini ada hubungannya tetapi type -a rmmemberi saya output sebagai,

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

Jadi apakah itu mempertimbangkan /bin/rmdalam kasus ini yang mengapa pengguna tidak diminta sebelum dihapus?

Ramesh
sumber
3
stracetidak mengabaikan alias, karena itu akan menyiratkan ada sesuatu yang diabaikan pada awalnya. Alias ​​adalah fitur shell. straceadalah program yang berbeda, dan di stracedalam konsep alias tidak ada, maka tidak ada yang perlu diabaikan. API yang disediakan oleh kernel untuk menjalankan program tidak memiliki konsep alias juga, jadi tidak ada cara shell dapat memberitahu strace tentang alias, bahkan jika itu mau.
kasperd
1
Jika Anda ingin stracealias, Anda harus ke straceshell, yang mengimplementasikan alias. Ada beberapa pendekatan yang dapat Anda ambil untuk melakukan itu: strace -p $$ &atau strace bashatau strace sh -c 'rm ramesh'(yang terakhir juga akan mengabaikan alias, tetapi untuk alasan yang sama sekali berbeda.)
kasperd

Jawaban:

20

stracetidak berjalan rm -ikarena alasan yang sama dengan:

echo rm

tidak menghasilkan rm -i.

Alias ​​adalah fitur dari beberapa shell untuk memungkinkan beberapa string secara otomatis diganti dengan yang lain ketika ditemukan dalam posisi perintah.

Di:

alias foo='whatever'
foo xxx

Kerang memperluas itu ke:

whatever xxx

dan yang mengalami putaran interpretasi lain, dalam hal itu mengarah pada melaksanakan whateverperintah.

alias hanya diperluas ketika ditemukan di posisi perintah (sebagai kata pertama dari baris perintah).

zshmendukung alias global .

Anda bisa melakukannya:

alias -g rm='rm -i'

Tetapi Anda tidak akan mau, karena itu berarti:

echo rm

akan menampilkan rm -imisalnya.

Stéphane Chazelas
sumber
8

stracemenggunakan PATHvariabel lingkungan untuk menemukan program yang akan dilacak, daripada mengeksekusi melalui shell (yang akan mengacaukan output). Shell alias bukan program, ini fitur shell, jadi straceabaikan saja.

Berlari strace strace rmagak mencerahkan, juga menarik secara rekursif.

Menandai
sumber
5

Alias ​​adalah fitur dari shell Anda. Namun, strace mengeksekusi perintah secara langsung (menggunakan execve, mungkin), yang tidak melibatkan shell. (Jika strace mengeksekusi perintah yang diberikan melalui shell, maka output dari strace akan berisi semua syscalls eksekusi shell daripada hanya mereka yang dari proses yang menarik.)

Selain itu, ketika Anda menjalankan strace rm ramesh, shell interaktif tidak berusaha untuk mengganti alias Anda dalam argumen untuk strace, karena itu akan sangat membingungkan bagi semua orang. Shell hanya memperluas alias yang muncul di posisi pertama pada baris perintah.

Greg Hewgill
sumber
2

strace menggunakan execve c functionseperti find command, Namun find uses exec functionAnda tidak dapat menggunakan aliases, built-in shell commandatau sebagainya.

Kamu harus melakukan:

strace /bin/rm -i ramesh
Teluk Persia
sumber
2

Untuk membangun jawaban Stéphane Chazelas, jika Anda mendefinisikan

alias strace="strace "

(dengan spasi di akhir) maka perintah

strace rm ramesh

akan diproses sebagai

strace rm -i ramesh

Tetapi bahkan ini hanya akan berfungsi untuk kata pertama setelah kata strace, jadi itu tidak akan berlaku langsung untuk contoh Anda (di mana Anda memiliki opsi intervensi).  Tetapi, jika Anda mendefinisikan

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

kemudian

my_strace rm ramesh

akan diproses sebagai

strace -ff -e trace=file rm -i ramesh
G-Man Mengatakan 'Reinstate Monica'
sumber
2

Tidak ada alias di sini

Mari kita asumsikan kita memiliki definisi alias alias rm='rm -i'di ~/.bashrc. Alias ​​menambahkan opsi untuk meminta sebelum menghapus setiap file:

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

Ini bukan kesalahan stracekarena tidak menggunakan alias:
Tidak ada hubungannya dengan alias.

Di perintah

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

Kata-kata rmdan ./filehanya argumen untuk strace untuk saat ini - shell tidak dapat memperluas alias rm, karena tidak dapat mengetahui bahwa strace akan menggunakan argumen ini sebagai perintah nanti.

Secara umum, alias perintah hanya dapat digunakan di mana perintah bisa.

Alias ​​adalah fitur dari shell, dan stracetidak menggunakan shell sama sekali ketika memanggil perintah dari baris perintah. exec()Sebagai gantinya, ia menggunakan perintah dan argumen dari baris perintah itu sendiri.

Di dalam strace, perintah akan dipanggil dengan sesuatu yang mirip exec("rm", "file"), dan exec()akan ditemukan /bin/rmdi PATH - tanpa menggunakan shell.

Shell eksplisit

Sekarang, mengapa tidak menyertakan shell dalam straceperintah?

$ 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 ... itu tidak berhasil. rmbaru saja menghapus file, tanpa -iprompt.

Alias ​​interaktif

Alias ​​biasanya hanya diaktifkan di shell interaktif, baris perintah aktual di terminal.
Dengan alias contoh kami, mudah untuk melihat mengapa itu masuk akal: Jika rm -ialias akan diperluas di dalam skrip shell, mereka akan hang pada awalnya rmtanpa ada yang menekan y.

Alias ​​dikendalikan oleh opsi shell expand_aliases. Kita dapat mengatur opsi dengan bash +O expand_aliases -c .... Tapi itu tidak cukup, karena shell non-interaktif juga tidak akan membaca ~/.bashrc. Itu artinya, alias kita tidak hanya dimatikan oleh opsi, tetapi juga tidak ditentukan.

Berpura-pura menjadi interaktif

Cara mudah untuk menangani kedua bagian adalah dengan menggunakan opsi baris perintah -iuntuk membuat shell berpura-pura interaktif:

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

Akhirnya, -ialias digunakan!

Perhatikan bahwa Anda biasanya tidak menggunakan shell yang berjalan dengan -iopsi untuk scripting, bahkan jika Anda ingin memiliki alias Anda tersedia, misalnya.

Volker Siegel
sumber