Pertanyaan Bagaimana saya bisa menjalankan perintah sewenang-wenang yang kompleks menggunakan sudo melalui ssh?


Saya memiliki sistem yang saya hanya bisa login ke bawah nama pengguna saya (myuser), tapi saya harus menjalankan perintah sebagai pengguna lain (scriptuser). Sejauh ini, saya telah datang dengan yang berikut ini untuk menjalankan perintah yang saya butuhkan:

ssh -tq myuser@hostname "sudo -u scriptuser bash -c \"ls -al\""

Namun jika, ketika saya mencoba menjalankan perintah yang lebih kompleks, seperti [[ -d "/tmp/Some directory" ]] && rm -rf "/tmp/Some directory" Saya dengan cepat mendapat masalah dengan mengutip. Saya tidak yakin bagaimana saya bisa memberikan contoh perintah kompleks ini kepada bash -c, kapan \" sudah membatasi batas-batas perintah yang saya lewati (jadi saya tidak tahu bagaimana mengutip / tmp / Beberapa direktori, yang mencakup spasi.

Apakah ada solusi umum yang memungkinkan saya untuk meloloskan sembarang perintah, tidak peduli seberapa rumit / gila kutipannya, atau apakah ini semacam keterbatasan yang saya capai? Apakah ada solusi lain yang mungkin dan mungkin lebih mudah dibaca?


76
2017-09-02 09:21




Salin skrip ke $ jauh lalu jalankan. - Iain
Itu akan berhasil, tetapi saya menemukan solusi yang tidak meninggalkan file skrip di belakang (jika sesuatu gagal dll.) Akan menjadi sedikit lebih bersih. - VoY
memiliki skrip rm sendiri di akhir setiap run - thanasisk
Pertimbangkan untuk menggunakan kain fabfile.org. Dapat membuat hidup Anda jauh lebih mudah jika Anda harus melakukan sudo secara remote. - Nils Toedtmann
Jika Anda memiliki Ansible menginstal perintah ini menunjukkan dokumentasi untuk use case Anda: skrip ansible-doc - bbaassssiiee


Jawaban:


Trik yang saya gunakan terkadang adalah menggunakan base64 untuk menyandikan perintah, dan menyalurkannya ke bash di situs lain:

MYCOMMAND=$(base64 -w0 script.sh)
ssh user@remotehost "echo $MYCOMMAND | base64 -d | sudo bash"

Ini akan menyandikan skrip, dengan koma, backslash, tanda kutip, dan variabel apa pun di dalam string aman, dan mengirimkannya ke server lain. (-w0 diperlukan untuk menonaktifkan pembungkus garis, yang terjadi di kolom 76 secara default). Di sisi lain, $(base64 -d) akan memecahkan kode skrip dan mengisinya ke bash untuk dieksekusi.

Saya tidak pernah punya masalah dengan itu, tidak peduli betapa rumitnya naskah itu. Memecahkan masalah dengan melarikan diri, karena Anda tidak perlu melarikan diri. Itu tidak membuat file di host jarak jauh, dan Anda dapat menjalankan skrip yang sangat rumit dengan mudah.


138
2017-09-02 13:10



Atau bahkan: ssh user@remotehost "echo `base64 -w0 script.sh` | base64 -d | sudo bash" - Niklas B.
Perlu dicatat bahwa dalam banyak kasus Anda dapat mengganti lzop atau gzip untuk base64 untuk waktu transfer yang lebih cepat. Namun, mungkin ada kasus tepi. YMMV. - CodeGnome
Catatan bagus, tetapi jika itu adalah skrip, saya tidak berharap transfer apa pun menjadi lebih dari beberapa kb. - ThoriumBR
Ada penggunaan gema yang tidak berguna di sini juga. base64 script | ssh remotehost 'base64 -d | sudo bash' akan cukup :) - hobbs
Diuji hari ini dan bekerja dengan sempurna. Terima kasih teman-teman. - Soham Chakraborty


Lihat -tt pilihan? Membaca ssh(1) manual.

ssh -tt root@host << EOF
sudo some # sudo shouldn't ask for a password, otherwise, this fails. 
lines
of
code 
but be careful with \$variables
and \$(other) \`stuff\`
exit # <- Important. 
EOF

Satu hal yang sering saya lakukan adalah menggunakan vim dan gunakan :!cat % | ssh -tt somemachine menipu.


32
2017-09-02 13:01



Tentu saja :!cat % | (command) bisa dilakukan seperti :w !(command) atau :!(command) < %. - Scott
Iya nih. Baris saya adalah penyalahgunaan kucing - moebius_eye


Saya pikir solusi termudah adalah modifikasi dari komentar @ thanasisk.

Buat skrip, scp ke mesin, lalu jalankan.

Punya naskahnya rm sendiri di awal. Shell telah membuka file, jadi sudah dimuat, dan kemudian dapat dihapus tanpa masalah.

Dengan melakukan hal-hal dalam urutan ini (rm pertama, hal-hal lain kedua) itu bahkan akan dihapus ketika gagal di beberapa titik.


9
2017-09-02 11:26





Anda dapat menggunakan %q penspesifikasi format dengan printf untuk mengurus variabel yang melarikan diri untuk Anda:

cmd="ls -al"
printf -v cmd_str '%q' "$cmd"
ssh user@host "bash -c $cmd_str"

printf -v menulis output ke variabel (dalam hal ini, $cmd_str). Saya pikir ini adalah cara paling sederhana untuk melakukannya. Tidak perlu mentransfer file atau menyandikan string perintah (sebanyak yang saya suka triknya).

Berikut ini contoh yang lebih kompleks yang menunjukkan bahwa ia berfungsi untuk hal-hal seperti kurung siku dan ampersan juga:

$ ssh user@host "ls -l test"
-rw-r--r-- 1 tom users 0 Sep  4 21:18 test
$ cmd="[[ -f test ]] && echo 'this really works'"
$ printf -v cmd_str '%q' "$cmd"
$ ssh user@host "bash -c $cmd_str"
this really works

Saya belum mengujinya sudo tetapi harus sesederhana:

ssh user@host "sudo -u scriptuser bash -c $cmd_str"

Jika Anda mau, Anda dapat melewati langkah dan menghindari membuat variabel antara:

$ ssh user@host "bash -c $(printf '%q' "$cmd")"
this really works

Atau bahkan hindari membuat variabel sepenuhnya:

ssh user@host "bash -c $(printf '%q' "[[ -f test ]] && echo 'this works as well'")"

7
2017-09-04 20:10



ini adalah solusi yang luar biasa. Saya sebenarnya harus menggunakan printf sebelumnya untuk situasi yang sama, tetapi saya selalu melupakannya. Terima kasih telah memposting ini :-) - Jon L.


Inilah cara "benar" (sintaksis) untuk mengeksekusi sesuatu seperti ini di bash:

ssh user@server "$( cat <<'EOT'
echo "Variables like '${HOSTNAME}' and commands like $( uname -a )"
echo "will be interpolated on the server, thanks to the single quotes"
echo "around 'EOT' above.
EOT
)"

ssh user@server "$( cat <<EOT
echo "If you want '${HOSTNAME}' and $( uname -a ) to be interpolated"
echo "on the client instead, omit the the single quotes around EOT."
EOT
)"

Untuk penjelasan menyeluruh tentang cara kerjanya, silakan lihat https://stackoverflow.com/a/21761956/111948


6
2018-05-28 17:48





Apakah Anda sadar bahwa Anda dapat menggunakannya sudo untuk memberi Anda shell di mana Anda dapat menjalankan perintah sebagai pengguna yang dipilih?

-i, --login

Jalankan shell yang ditentukan oleh entri basis data kata sandi target pengguna sebagai shell login. Ini berarti file sumber daya khusus login seperti                    .profile atau .login akan dibaca oleh shell. Jika perintah ditentukan, ia diteruskan ke shell untuk dieksekusi melalui opsi -c shell. Jika tidak                    perintah ditentukan, shell interaktif dijalankan. sudo mencoba mengubah direktori home pengguna sebelum menjalankan shell. Perusahaan                    mand dijalankan dengan lingkungan yang mirip dengan yang akan diterima pengguna saat masuk. Bagian Lingkungan Perintah dalam sudoers (5) dokumen manual                    bagaimana cara opsi -i mempengaruhi lingkungan di mana perintah dijalankan ketika kebijakan sudoers sedang digunakan.


4
2017-09-03 09:22



ini sepertinya solusi yang jelas bagi saya. > sudo -i -u brian - code_monk
Yang paling baik bila dikombinasikan dengan "ssh -t" dalam kasus akses jarak jauh. Yang termasuk dalam pertanyaan, tetapi beruang mengulangi untuk orang-orang "Saya tidak bisa membaca ini / seluruh / halaman". :) - dannysauer


Anda dapat menentukan skrip di komputer lokal Anda dan kemudian cat dan menyalurkannya ke mesin jarak jauh:

user@host:~/temp> echo "echo 'Test'" > fileForSsh.txt
user@host:~/temp> cat fileForSsh.txt | ssh localhost

Pseudo-terminal will not be allocated because stdin is not a terminal.
stty: standard input: Invalid argument
Test

3
2017-09-02 09:39



UUOC Anda dapat menggunakan < - Iain
Bisakah Anda memodifikasi contoh untuk disertakan sudo -u scriptuser? Apakah heredoc dapat digunakan mengingat saya perlu memiliki variabel dalam skrip yang akan saya pipihkan ke mesin? - VoY
Saya mencoba: echo "sudo `cat fileForSsh.txt`" | ssh ... tapi saya terus mendapatkan sudo: sorry, you must have a tty to run sudo. - jas_raj
Meskipun pertanyaan ini dapat membantu jika Anda bisa mendapatkan /etc/sudoers file berubah - jas_raj
Ini bekerja untuk saya: ssh -tq user@host "sudo bash -s" < test.sh - AVee


Sederhana dan mudah.

ssh user @ servidor "bash -s" <script.sh


1
2017-09-03 20:15