Gunakan perintah sistem alih-alih Bash builtin tanpa menentukan path lengkap

17

Saya menggunakan Bash sebagai shell interaktif saya dan saya bertanya-tanya apakah ada cara mudah untuk membuat Bash menjalankan perintah sistem alih-alih perintah shell builtin dalam kasus di mana mereka berdua memiliki nama yang sama.

Sebagai contoh, gunakan sistem kill(dari util-linux) untuk mencetak id proses (pid) dari proses yang disebutkan (es) alih-alih mengirim sinyal:

$ /bin/kill -p httpd
2617
...

Tanpa menentukan path lengkap dari perintah sistem, Bash builtin digunakan sebagai ganti perintah sistem. The killbuiltin tidak memiliki -ppilihan sehingga perintah gagal:

$ kill -p httpd
bash: kill: p: invalid signal specification

Saya mencoba jawaban yang tercantum di Make bash menggunakan perintah `time` eksternal daripada built-in shell tetapi kebanyakan dari mereka hanya bekerja karena timesebenarnya kata kunci shell - bukan builtin shell .

Selain menonaktifkan Bash bawaan untuk sementara enable -n kill, solusi terbaik yang saya lihat sejauh ini adalah menggunakan:

$(which kill) -p httpd

Apakah ada cara lain yang lebih mudah (melibatkan lebih sedikit pengetikan) untuk mengeksekusi perintah eksternal daripada menggunakan shell?

Catatan itu killhanyalah sebuah contoh dan saya ingin solusi umum yang mirip dengan cara awalan dengan commandbuiltin mencegah fungsi yang memiliki nama yang sama dengan perintah eksternal dijalankan. Dalam kebanyakan kasus, saya biasanya lebih suka menggunakan versi builtin karena menghemat forking proses baru dan beberapa kali builtin memiliki fitur yang tidak dimiliki perintah eksternal.

Anthony G - keadilan untuk Monica
sumber
Menutup which killdi backticks (tidak bisa memasukkannya ke dalam komentar) sedikit lebih pendek.
abligh
@ Bagus. Bagus. Saya telah menghabiskan waktu bertahun-tahun melatih diri untuk menggunakan sintaks er "baru" untuk substitusi perintah. :)
Anthony G - justice for Monica
@abligh: FYI, Anda dapat memasukkan `backticks` ke dalam komentar dengan mendahului mereka dengan garis miring terbalik (\). Tapi ada alasan untuk tetap bertahan $(…)- lihat ini , ini , dan ini .
G-Man Mengatakan 'Reinstate Monica'

Jawaban:

20

Dengan asumsi envada di jalur Anda:

env kill -p http

envmenjalankan file yang dapat dieksekusi yang dinamai dengan argumen pertamanya di lingkungan yang (mungkin) dimodifikasi; karena itu, ia tidak tahu tentang atau bekerja dengan perintah built-in shell.

Ini menghasilkan beberapa kontrol kontrol pekerjaan shell, tetapi tidak bergantung pada perintah eksternal:

exec kill -p bash &

execmembutuhkan executable untuk mengganti shell saat ini, jadi tidak menggunakan built-in. Pekerjaan dijalankan di latar belakang sehingga Anda mengganti shell latar bercabang, bukan shell Anda saat ini.

chepner
sumber
2
envjelas merupakan jawaban IMHO yang tepat.
Abligh
@abligh: Anda benar dalam mengomentari jawaban saya yang dihapus. command -p cmdmemanggil perintah eksternal zsh, bukan bash.
cuonglm
6
(exec kill -p http)menyebabkan pekerjaan mengganti sub-shell alih-alih shell Anda saat ini dan Anda tidak harus berurusan dengan cruft kontrol pekerjaan.
Michael Hoffman
1
@AnthonyGeoghegan Memang, tetapi envjuga tidak tahu tentang builtin shell, karena itu bukan shell. Anda akan mendapatkan efek yang sama dengan niceatau xargsatau program lain seperti itu.
user253751
1

Cara paling sederhana untuk melakukan apa yang Anda inginkan adalah dengan meletakkan garis

alias kill="/bin/kill"

ke dalam ~/.bashrcfile Anda . Setelah itu, setiap login / doa baru dari bash akan menafsirkan "bunuh" sebagai /bin/kill.

Benjamin Staton
sumber
Saya sudah memikirkan alias dan itu adalah salah satu solusi yang tercantum dalam pertanyaan yang saya tautkan tetapi saya berharap untuk solusi yang lebih umum (mirip dengan commandsolusi) daripada membuat alias terpisah untuk setiap perintah "dibayangi". Sekarang saya telah mengedit pertanyaan saya untuk membuatnya lebih jelas dan lebih eksplisit. Dalam kebanyakan kasus, saya biasanya lebih suka menggunakan versi builtin karena proses dapat ditentukan oleh ID pekerjaan. Bagaimanapun, terima kasih.
Anthony G - keadilan untuk Monica
1

Jika Anda tahu solusi yang membutuhkan pengetikan dan Anda menginginkan solusi yang membutuhkan pengetikan yang lebih sedikit, buatlah:

runFile() { local cmd="$1"; shift; cmd="$(which "$cmd")" && "$cmd" "$@"; }

Menyingkat hal-hal yang biasanya membutuhkan usaha adalah keunggulan komputer.

PSkocik
sumber
1
Itu adalah poin umum yang baik jadi saya akan menjawab pertanyaan Anda. Selama beberapa tahun terakhir, saya telah membangun koleksi alias, fungsi dan skrip untuk sistem yang saya gunakan secara teratur. Namun, saya lebih suka menggunakan solusi yang tidak dikustomisasi jika memungkinkan karena kadang-kadang saya harus mengerjakan instalasi baru atau server yang tidak saya atur. Terima kasih.
Anthony G - keadilan untuk Monica
1

Dalam kasus yang sangat spesifik ini, perintahnya pgrepsama dengan kebutuhan.

Secara umum, fungsi bekerja. Dari "perintah file":

fcmd(){ local a=$1; shift; $(which "$a") "$@"; }

panggilan sebagai

fcmd kill -p httpd

Tetapi jika Anda perlu mengetik lebih sedikit, tidak ada cara yang lebih pendek dari alias yang baik.

Dari konsep "daftar pid" (lp):

alias lp='/bin/kill -p'

lalu ketikkan:

lp httpd

sumber
0

(Dalam zsh) Anda dapat mengawali nama perintah apa pun dengan tanda = untuk mendapatkan versi sistem alih-alih builtin. Ini juga merupakan cara praktis untuk menghindari alias apa pun yang mengacaukan skenario tertentu.

$ =kill -p httpd
Caleb
sumber
1
Saya mencobanya dengan Bash versi 4.3.30 dan tidak berhasil. Saya belum pernah melihat sintaks seperti itu sebelumnya; dapatkah Anda menambahkan tautan ke tempat fitur ini didokumentasikan? Saya biasanya akan awalan alias dengan backslash untuk menjalankan versi perintah yang tidak alias.
Anthony G - keadilan untuk Monica
@Anthony mungkin ini satu- zshsatunya. Saya menggunakannya secara teratur tetapi saya akan memeriksa bashdari komputer besok.
Caleb
Saya menduga mungkin ada beberapa shell yang saya tidak kenal (saya hanya akrab dengan bash, dash dan csh). Ada jawaban lain (sejak dihapus) yang hanya berfungsi untuk zsh. Sementara saya menandai pertanyaan ini dengan bashdan menggunakannya dalam judul, Anda harus menyimpan jawaban ini karena pengguna zsh tetap akan menemukan manfaatnya.
Anthony G - keadilan untuk Monica
-1

Anda dapat mengirim laporan bug terhadap killhalaman manual Anda dan bertanya mengapa ini termasuk opsi non-standar yang diambil pkilldan digunakan pkillkapan pun Anda ingin mendapatkan fitur daripkill.

Jika Anda menelepon:

pkill httpd

Anda menghindari masalah yang Anda gambarkan.

schily
sumber