Ketika saya mencoba menjalankan pkill -f
dari jarak jauh melalui ssh, dan coba buang kemungkinan kode kesalahan (untuk melanjutkan skrip saya yang lain meskipun tidak ada proses yang ditemukan), || true
tidak berperilaku seperti yang saya harapkan.
$ pkill asdf || true
$ echo $?
0
$ pkill -f asdf || true
$ echo $?
0
$ ssh [email protected] "pkill asdf || true"
$ echo $?
0
$ ssh [email protected] "pkill -f asdf || true"
255
Saya kira itu adalah ssh yang mengembalikan 255, bukan perintah di antara tanda kutip, tetapi mengapa?
Jawaban yang Diterima:
Anggapan Anda bahwa itu ssh
sendiri yang mengembalikan status keluar 255 benar. ssh
halaman manual menyatakan bahwa:
ssh keluar dengan status keluar dari perintah jarak jauh atau dengan 255 jika terjadi kesalahan.
Jika Anda hanya menjalankan ssh [email protected] "pkill -f asdf"
, kemungkinan besar Anda akan mendapatkan status keluar 1
, sesuai dengan pkill
status untuk “Tidak ada proses yang cocok ”.
Bagian yang menantang adalah memahami mengapa terjadi kesalahan dengan SSH saat Anda menjalankan
ssh [email protected] "pkill -f asdf || true"
Perintah jarak jauh SSH
Server SSH meluncurkan shell untuk menjalankan perintah jarak jauh. Berikut ini contoh tindakannya:
$ ssh server "ps -elf | tail -5"
4 S root 35323 1024 12 80 0 - 43170 poll_s 12:01 ? 00:00:00 sshd: anthony [priv]
5 S anthony 35329 35323 0 80 0 - 43170 poll_s 12:01 ? 00:00:00 sshd: [email protected]
0 S anthony 35330 35329 0 80 0 - 28283 do_wai 12:01 ? 00:00:00 bash -c ps -elf | tail -5
0 R anthony 35341 35330 0 80 0 - 40340 - 12:01 ? 00:00:00 ps -elf
0 S anthony 35342 35330 0 80 0 - 26985 pipe_w 12:01 ? 00:00:00 tail -5
Perhatikan bahwa shell default adalah bash
dan bahwa perintah jarak jauh bukanlah perintah sederhana tetapi sebuah saluran, “urutan dari satu atau lebih perintah yang dipisahkan oleh operator kontrol |
”.
Shell Bash cukup pintar untuk menyadari bahwa jika perintah diteruskan oleh -c
option adalah perintah sederhana, ia dapat mengoptimalkan dengan tidak benar-benar membuat proses baru, yaitu, secara langsung exec
s perintah sederhana alih-alih melalui langkah ekstra fork
ing sebelum exec
s. Berikut adalah contoh yang terjadi saat Anda menjalankan perintah sederhana jarak jauh (ps -elf
dalam hal ini):
$ ssh server "ps -elf" | tail -5
1 S root 34740 2 0 80 0 - 0 worker 11:49 ? 00:00:00 [kworker/0:1]
1 S root 34762 2 0 80 0 - 0 worker 11:50 ? 00:00:00 [kworker/0:3]
4 S root 34824 1024 31 80 0 - 43170 poll_s 11:51 ? 00:00:00 sshd: anthony [priv]
5 S anthony 34829 34824 0 80 0 - 43170 poll_s 11:51 ? 00:00:00 sshd: [email protected]
0 R anthony 34830 34829 0 80 0 - 40340 - 11:51 ? 00:00:00 ps -elf
Saya pernah menemukan perilaku ini sebelumnya, tetapi saya tidak dapat menemukan referensi yang lebih baik selain jawaban AskUbuntu ini.
Terkait:Apa perbedaan antara titik koma dan ampersand ganda &&?perilaku membunuh
Sejak pkill -f asdf || true
bukan perintah sederhana (ini adalah daftar perintah), pengoptimalan di atas tidak dapat terjadi sehingga ketika Anda menjalankan ssh [email protected] "pkill -f asdf || true"
, sshd
garpu proses dan eksekutif bash -c "pkill -f asdf || true"
.
Seperti yang ditunjukkan oleh jawaban ctx, pkill
tidak akan mematikan prosesnya sendiri. Namun, itu akan matikan proses lain yang baris perintahnya cocok dengan -f
pola. bash -c
perintah cocok dengan pola ini sehingga menghentikan proses ini – induknya sendiri (seperti yang terjadi).
Server SSH kemudian melihat bahwa proses shell yang dimulai untuk menjalankan perintah jarak jauh dimatikan secara tidak terduga sehingga melaporkan kesalahan ke klien SSH.