Saya mendefinisikan fungsi shell (sebut saja clock
), yang ingin saya gunakan sebagai pembungkus untuk perintah lain, mirip dengan time
fungsi, misalnya clock ls -R
.
Fungsi shell saya melakukan beberapa tugas dan kemudian diakhiri dengan exec "$@"
.
Saya ingin fungsi ini berfungsi bahkan dengan built-in shell, mis. clock time ls -R
Harus menampilkan hasil dari time
built-in, dan tidak /usr/bin/time
dapat dieksekusi. Tapi exec
selalu berakhir menjalankan perintah saja.
Bagaimana saya bisa membuat fungsi Bash saya berfungsi sebagai pembungkus yang juga menerima shell built-in sebagai argumen?
Sunting : Saya baru tahu bahwa time
itu bukan Bash built-in, tetapi kata khusus yang dicadangkan terkait dengan saluran pipa. Saya masih tertarik dengan solusi untuk built-in walaupun tidak bekerja time
, tetapi solusi yang lebih umum akan lebih baik.
sumber
exec bash -c \' "$@" \'
. Kecuali jika perintah Anda pada parameter pertama dikenali sebagai skrip shell, maka itu akan ditafsirkan sebagai biner untuk dijalankan secara langsung. Atau, dan lebih sederhana, lewatkan sajaexec
dan panggil"@"
dari shell asli Anda.Jawaban:
Anda mendefinisikan fungsi bash. Jadi, Anda sudah menggunakan bash shell saat menjalankan fungsi itu. Jadi fungsi itu bisa terlihat seperti:
Fungsi itu dapat dipanggil dengan bash builtin, kata-kata khusus, perintah, fungsi-fungsi tertentu lainnya:
Alias:
Bash bawaan:
Fungsi lain:
Dapat dieksekusi:
sumber
$@
danexec $@
, jika saya tahu saya menjalankan perintah yang sebenarnya?exec
, perintah itu menggantikan shell. Oleh karena itu tidak ada builtin, alias, kata-kata khusus yang dicadangkan, kata-kata yang didefinisikan lagi, karena dieksekusi dieksekusi melalui system callexecve()
. Syscall itu mengharapkan file yang dapat dieksekusi.exec $0
ada satu proses, sementara$@
masih memiliki dua.$@
memiliki shell yang berjalan sebagai orangtua dan perintah sebagai proses anak. Tetapi ketika Anda ingin menggunakan builtin, alias dan sebagainya, Anda harus mempertahankan shell. Atau mulai yang baru.Satu-satunya cara untuk meluncurkan shell builtin atau kata kunci shell adalah untuk meluncurkan shell baru karena exec "mengganti shell dengan perintah yang diberikan". Anda harus mengganti baris terakhir Anda dengan:
Ini bekerja dengan baik bawaan dan kata-kata yang dipesan; prinsipnya sama.
sumber
Jika pembungkus perlu memasukkan kode sebelum perintah yang diberikan, alias akan berfungsi karena mereka diperluas pada tahap yang sangat awal:
Alias hampir secara harfiah dimasukkan sebagai pengganti kata alias, jadi jejaknya
;
penting - itu membuatnyaclock time foo
berkembang menjadido this; do that; time foo
.Anda dapat menyalahgunakan ini untuk membuat alias ajaib yang bahkan memotong kutipan.
Untuk memasukkan kode setelah perintah, Anda bisa menggunakan kait "DEBUG".
Secara khusus:
Hook masih berjalan sebelum perintah, tetapi ketika ia kembali
false
itu memberitahu bash untuk membatalkan eksekusi (karena hook sudah menjalankannya melalui eval).Sebagai contoh lain, Anda dapat menggunakan ini untuk alias
command please
kesudo command
:sumber
Satu-satunya solusi yang saya dapat sampai sejauh ini adalah melakukan analisis kasus untuk membedakan apakah argumen pertama adalah perintah, bawaan, atau kata kunci, dan gagal dalam kasus terakhir:
Namun, itu tidak menangani
time
, jadi mungkin ada solusi yang lebih baik (dan lebih ringkas).sumber