Saya mencoba untuk membuat cadangan beberapa file melalui SSH tetapi alih-alih tar
yang saya inginkan saya mendapat folder rumah saya. Saya melakukan beberapa pengujian lebih lanjut dan intinya adalah:
ssh root@server /bin/sh -c "cd /boot && ls -l"
Yang mengejutkan saya daftar file dalam /root
tidak /boot
. Tetapi jika saya menjalankan seluruh /bin/sh
perintah dari terminal dengan benar cd
dan mencetak /boot
file.
Apa yang sedang terjadi disini?
shell
ssh
cd-command
Ambroz Bizjak
sumber
sumber
ssh root@server /bin/sh -c "ls -l /boot"
?Jawaban:
ssh tidak membiarkan Anda menentukan perintah secara tepat, seperti yang telah Anda lakukan, sebagai serangkaian argumen untuk diteruskan ke execvp pada host jarak jauh. Sebaliknya itu menggabungkan semua argumen menjadi string dan menjalankannya melalui shell jarak jauh. Ini menonjol sebagai cacat desain utama dalam ssh menurut saya ... itu adalah alat unix berperilaku baik dalam banyak hal, tetapi ketika tiba saatnya untuk menentukan perintah yang ia pilih untuk menggunakan string monolitik tunggal alih-alih argv, seperti itu dirancang untuk MSDOS atau apalah!
Karena ssh akan meneruskan perintah Anda sebagai string tunggal
sh -c
, Anda tidak perlu menyediakan sendirish -c
. Ketika Anda melakukannya, hasilnya adalahdengan kutipan aslinya hilang. Jadi perintah yang dipisahkan oleh
&&
adalah:Yang pertama menjalankan shell dengan teks perintah "cd" dan
$0
="boot"
. Perintah "cd" berhasil diselesaikan,$0
itu tidak relevan, dan yang/bin/sh -c
menunjukkan keberhasilan, maka yangls -l
terjadi.sumber
ssh
berperilaku seperti itu, jika tidak, itu harus dipanggilsexec
, bukanssh
.ssh
adalah versi amanrsh
(yang berperilaku sama dalam hal itu) danrlogin
(rsh
dipanggilrlogin
saat tidak melewati baris perintah). Sangat disayangkan bahwa itu tidak diterapkanrexec
juga."`printf "%q " "$@"`"
dengan bash'sprintf
untuk mengutip string atau string dengan shell escapes.Ini masalah mengutip. Ssh sudah menjalankan perintah yang Anda berikan dalam sebuah shell. Ketika Anda melewati beberapa parameter, mereka digabungkan dengan spasi di antaranya untuk membangun string. Jadi perintah jarak jauh yang Anda jalankan dari jarak jauh adalah
/bin/sh -c cd /boot && ls -l
(tidak ada tanda kutip, karena tanda kutip di perintah Anda ditafsirkan oleh shell lokal)./bin/sh -c cd /boot
menjalankan/bin/sh
dan memberi tahu untuk menjalankan perintahcd
dan juga untuk mengatur$0
ke/boot
. Setelah ini selesai, shell induk (yang diluncurkan olehsshd
) berjalanls -l
.Dalam kasus Anda, hapus saja
sh -c
yang benar-benar tidak berguna kecuali shell jarak jauh Anda (seperti yang ditunjukkan dalam/etc/passwd
atau basis data kata sandi lainnya) tidak memahami perintah ini.Jika Anda perlu memanggil shell yang berbeda, Anda harus mengutip perintah remote untuk melindunginya dari ekspansi oleh shell remote yang dipanggil oleh
sshd
. Misalnya, jika shell login Anda putus-putus dan Anda ingin menjalankan perintah bash:sumber
Saya pikir ini lebih berkaitan dengan bagaimana opsi semakin diurai oleh shell. Misalnya, ini berfungsi:
Ini memiliki masalah yang sama dengan perintah Anda:
Jika Anda mengaktifkan
-v
peralihan kessh
Anda dapat melihat apa yang terjadi:Perintah 1:
Perintah 2:
Biasanya ketika mengirim perintah melalui
ssh
Anda harus memberi perhatian khusus pada kutipan dan bungkus kutipan dalam tanda kutip karena berbagai lapisan menghapusnya. Juga jangan repot mengirim/bin/sh
.Anda dapat melakukan hal yang sangat berguna setelah Anda memahami kutipan
ssh
seperti berikut ini. Ini akan menjalankan perintah pada server jauh tetapi mengumpulkan hasil dalam file secara lokal pada sistem tempat Anda menjalankanssh
perintah:atau ini, tempat Anda menempatkan direktori pada server jarak jauh dan membuatnya di sistem lokal:
Referensi
sumber
Biasanya Anda tidak harus menentukan shell apa yang akan digunakan. Ini bekerja:
Tetapi jika shell default Anda bermasalah, maka pastikan Anda mengutip seluruh perintah, termasuk doa shell. Salah satu dari karya-karya berikut
sumber
cd /boot && pwd
bekerja di semua cangkang keluarga besar (Bourne, csh, rc),/bin/sh -c "cd /boot && pwd"
tidak akan berfungsi jika cangkang jarak jauh adalah darirc
keluarga"
yang tidak spesial.