Gunakan kasing / contoh praktis untuk Bash 'builtin exec


12

Pertimbangkan ini dari dokumentasi Bash 'builtin exec:

exec mengganti shell tanpa membuat proses baru

Berikan kasus penggunaan / contoh praktis. Saya tidak mengerti bagaimana ini masuk akal.

I googled dan menemukan tentang I / O redirection . Bisakah Anda menjelaskannya dengan lebih baik?


Jawaban:


18

execsering digunakan dalam skrip shell yang terutama bertindak sebagai pembungkus untuk memulai binari lainnya. Sebagai contoh:

#!/bin/sh

if stuff;
    EXTRA_OPTIONS="-x -y -z"
else
    EXTRA_OPTIONS="-a foo"
fi

exec /usr/local/bin/the.real.binary $EXTRA_OPTIONS "$@"

sehingga setelah pembungkus selesai berjalan, biner "asli" mengambil alih dan tidak ada lagi jejak skrip pembungkus yang untuk sementara menempati slot yang sama di tabel proses. Biner "asli" adalah anak langsung dari apa pun yang diluncurkan, bukan cucu.

Anda menyebutkan juga pengalihan I / O dalam pertanyaan Anda. Itu adalah kasus penggunaan yang sangat berbeda execdan tidak ada hubungannya dengan mengganti shell dengan proses lain. Ketika exectidak memiliki argumen, seperti:

exec 3>>/tmp/logfile

lalu pengalihan I / O pada baris perintah berlaku dalam proses shell saat ini, tetapi proses shell saat ini terus berjalan dan beralih ke perintah berikutnya dalam skrip.


1
Anda dapat mengatakan bahwa kedua kasus terkait dalam keduanya, execmemberi tahu shell untuk tidak melakukan tindakan (menjalankan perintah atau melakukan pengalihan) dalam proses anak, tetapi dalam proses yang sama.
Stéphane Chazelas

5

Saya telah menggunakan shell execbuiltin untuk mendapatkan ID proses (PID) ke program Java. Mungkin ada cara untuk mendapatkan PID dari dalam Jawa sekarang, tetapi beberapa tahun yang lalu, tidak ada. Setelah suatu proses memiliki PID-nya sendiri, ia dapat menuliskannya ke file PID (lihat /var/run/nama file dengan akhiran '.pid') untuk memungkinkan program manajemen mengetahui PID dari proses yang sedang berjalan, dan untuk mencegah instance kedua dari server yang sama agar tidak berjalan. Ini berfungsi seperti ini:

exec java -cp=YourServer.jar StartClass -p $$

Kode dalam main()metode class StartClassmenangani argumen parsing dan dapat menemukan ID prosesnya sendiri.


2

Untuk bersenang-senang, jalankan program berikut (diterjemahkan ke bahasa implementasi pilihan Anda) di latar belakang sistem dengan penghitungan dan batasan proses pengguna.

while(true) fork();

Sekarang setiap slot di tabel proses yang diizinkan untuk Anda penuh dengan salinan program yang sedang berjalan, bagaimana Anda bermaksud membunuhnya? Peluncuran kill (1) membutuhkan slot proses lain, yang tidak dapat Anda miliki. Tentu akan berguna untuk mengganti shell dengan perintah kill ...

exec /bin/kill -9 -1

(Asumsikan sistem Anda telah mematikan (1) di / bin / kill. "Exec` that kill` -9 -1 "berpotensi lebih aman.) Ini mengirimkan SIGKILL ke setiap proses yang Anda bisa.

(Catatan: Jangan keluar dari shell peluncuran Anda kecuali batas proses selalu mengizinkan login baru slot proses untuk shellnya. Ini bisa sedikit lebih sulit untuk dibersihkan jika Anda melakukannya. Saya tentu saja tidak melakukan ini di awal 90-an. Tidak.)


3
(1) Jawaban ini akan sedikit lebih baik jika Anda benar-benar menunjukkan execperintah yang akan berguna dalam situasi ini. (2) Jawaban ini agak kuno; yang killperintah telah menjadi perintah builtin di bash selama bertahun-tahun, terutama karena kekhawatiran ini.
G-Man Mengatakan 'Reinstate Monica'

@ G-Man: Anda mengerti bahwa item Anda (2) membuat jawaban ini respons yang tepat untuk OP?
Eric Towers

Tidak, saya tidak mengerti itu. Tolong jelaskan kepada saya.
G-Man Mengatakan 'Reinstate Monica'

4
Saya tidak mengikuti Anda. Pertanyaannya tidak menanyakan contoh praktis dari semua perintah bash builtin; ia meminta contoh exec- dan fakta bahwa killbuiltin tidak benar-benar ada hubungannya dengan execbuiltin.
G-Man Mengatakan 'Reinstate Monica'

1
Saya baru saja membaca pembaruan Anda untuk jawaban Anda. (1) Coba tebak? Jika tabel proses penuh, maka substitusi perintah (misalnya, `which kill`) juga tidak akan berfungsi. (2) BTW, $(…)formulir direkomendasikan di atas `…`formulir. (3) Tapi tidak ada yang berbahaya menebak di direktori. Jika Anda mengetik secara tidak sengaja exec /binn/kill, Anda hanya akan mendapatkan pesan kesalahan, dan shell Anda tidak akan hilang. (4) Tetapi Anda bahkan tidak perlu khawatir tentang direktori apa yang digunakan kill.  Sama seperti perintah normal, jadi berfungsi (dengan asumsi Anda ada di jalur pencarian Anda). exec$PATHexec kill …/bin
G-Man Mengatakan 'Reinstate Monica'

1
  • Ini mirip dengan contoh Bruce yang perlu mengetahui PID suatu proses:

    (cmdpid = $ BASHPID; (sleep 300; bunuh "$ cmdpid") & exec -long-running-command )

    di mana kamu

    1. Mulai subkulit (luar (dan )),
    2. Temukan PID dari subkulit. ( $$akan memberi Anda PID dari shell utama.)
    3. Lepaskan sub-subkulit yang membunuh proses Anda setelah batas waktu, dan
    4. Jalankan perintah dalam proses subkulit yang Anda buat pada langkah 1.

    Ini akan berjalan long-running-command, tetapi hanya untuk jumlah waktu yang ditentukan sebelumnya dan terbatas. 

  • Ini agak sembrono, tetapi, jika Anda memutuskan bahwa Anda ingin menjadi root (atau pengguna lain) untuk sisa sesi login Anda, Anda bisa exec su.

    Sebenarnya, saya bisa membayangkan skenario di mana ini akan sangat berguna. Misalkan Anda masuk ke sistem jarak jauh, dan, untuk beberapa alasan, ada masalah dengan memutuskan koneksi dan memulai koneksi baru. Misalnya, anggap sistem remote memiliki firewall yang mengikuti jadwal. Anda diizinkan untuk terhubung ketika Anda melakukannya, dan koneksi yang dibuat tidak ditutup, tetapi pada saat ini, koneksi baru tidak diterima.

    Anda telah melakukan apa yang ingin Anda lakukan, dan Anda siap untuk keluar. Temanmu, Bob, berada di ruangan bersamamu, dan dia ingin melakukan beberapa pekerjaan pada sistem jarak jauh - tetapi dia tidak akan dapat terhubung. Jadi, Anda mengetik exec su - bob, dan, ketika prompt kata sandi muncul, balikkan workstation kepadanya. Sekarang tidak ada proses dengan UID Anda (kecuali Anda menjalankan sesuatu di latar belakang), jadi Bob tidak akan bisa dipusingkan dengan file Anda. Dia akan secara efektif mengambil alih koneksi Anda (dengan persetujuan dan kerja sama Anda).

    Catatan:

    • Tentu saja ini tidak akan berhasil jika Anda tidak diizinkan berlari su.
    • Ini akan dicatat, jadi Anda mungkin perlu menjelaskan motif Anda kepada seseorang. Karena Anda menghindari kebijakan (jadwal firewall), Anda mungkin mendapat masalah.
    • Saya tidak menjamin bahwa itu 100% aman. Misalnya, whomungkin masih akan menampilkan nama Anda. Bisa dibayangkan bahwa beberapa program (yang ditulis dengan buruk) akan menggunakannya untuk berpikir bahwa Bob adalah Anda, dan memberinya akses ke sumber daya Anda.
    • Jika sistem melakukan audit, tindakan Bob mungkin diaudit dengan nama Anda.

Perhatikan bahwa dalam praktik di sebagian besar shell, (a;b)sudah sama (a;exec b)dengan shell mengoptimalkan garpu untuk perintah terakhir dalam subkulit. Satu-satunya pengecualian tampaknya bashdan mksh. Menggunakan execmembantu untuk menjaminnya.
Stéphane Chazelas
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.