Bagaimana cara menjalankan skrip bash lokal pada mesin jarak jauh melalui ssh?

51

Saya mencari cara untuk mendorong konfigurasi dari satu mesin pusat ke beberapa mesin jarak jauh tanpa perlu menginstal apa pun di mesin jarak jauh.

Tujuannya adalah untuk melakukan sesuatu seperti yang Anda akan temukan dengan alat-alat seperti cfengine, tetapi pada satu set mesin yang tidak memiliki agen mengatur. Ini mungkin sebenarnya teknik yang baik untuk mengatur cfagentpada set mesin jarak jauh yang ada.

tremoloqui
sumber
Mirip dengan SO: stackoverflow.com/q/305035/435605
AlikElzin-kilaka
1
Pertanyaan aktual memiliki 23 upvotes di mana duplikat pada SO memiliki 55: P
MoJo

Jawaban:

55

Anda bisa melewatkan skrip dan menjalankannya secara sementara dengan memiparkannya dan mengeksekusi sebuah shell.

misalnya

echo "ls -l; echo 'Hello World'" | ssh me@myserver /bin/bash

Secara alami, "ls -l; echo 'Hello World'"bagian itu bisa diganti dengan skrip bash yang disimpan dalam file di mesin lokal.

misalnya

cat script.sh | ssh me@myserver /bin/bash

Tepuk tangan!

tremoloqui
sumber
2
Bagaimana cara membuat menjalankan ini sebagai sudo pada system.eg terpencil Jika saya login remote server saya biasanya akan menjalankan ini sebagai sudo -u testuser script.sh
Sharjeel
Bagaimana jika skrip yang saya panggil melibatkan interaksi pengguna ???
Abhimanyu Srivastava
20

Ada beberapa cara untuk melakukannya.

1:

ssh user@remote_server 'bash -s' < localfile

2:

cat localfile  | ssh user@remote_server

3:

ssh user@remote_server "$(< localfile)"

nomor 3 adalah cara yang saya sukai, ini memungkinkan perintah interaktif misalnya su -S service nginx restart

(# 1 akan menggunakan sisa skrip sebagai input untuk pertanyaan kata sandi saat Anda menggunakan su -S.)

Paul Verschoor
sumber
4
Mengenai menjalankan skrip lokal pada mesin jarak jauh - Apakah ada cara untuk mengirim variabel sebagai argumen ke mesin jarak jauh ..? yaitu bersama dengan skrip, saya ingin mengirim variabel (memiliki beberapa baris) sebagai argumen ke mesin remote. Script kemudian bermaksud menggunakan variabel.
13

Saya akan merekomendasikan Fabric python untuk tujuan ini:

#!/usr/bin/python
# ~/fabfile.py

from fabric_api import *

env.hosts = ['host1', 'host2']
def deploy_script():
    put('your_script.sh', 'your_script.sh', mode=0755)
    sudo('./your_script.sh')

# from shell
$ fab deploy_script

Anda harus dapat menggunakan hal di atas untuk memulai. Konsultasikan dokumentasi Fabric yang sangat baik untuk melakukan sisanya. Sebagai tambahan, sangat mungkin untuk menulis skrip Anda sepenuhnya di dalam Fabric - tidak perlu menyalin, namun perlu dicatat bahwa untuk mengubah skrip di semua mesin, Anda hanya perlu mengedit salinan lokal dan memindahkannya. Selain itu, dengan sedikit lebih dari penggunaan dasar API, Anda dapat memodifikasi skrip berdasarkan host mana yang sedang berjalan dan / atau variabel lain. Ini semacam harapan pythonic.

Sam Halicke
sumber
Saya tidak berpikir ini persis menjawab pertanyaan, tapi saya suka ide itu dan saya bisa melihat Fabric sebagai alat yang berguna.
tremoloqui
1
@tremoloqui Fabric adalah pembungkus python di sekitar ssh - tidak ada yang perlu diinstal pada mesin target, kecuali skrip yang didorong. Yang, jika ditulis ulang sebagai serangkaian perintah Fabric (menggunakan rundan sudo), bahkan tidak diperlukan.
Izkata
5

Inilah tepatnya yang digunakan untuk Ansible. Tidak ada agen, Anda hanya perlu membuat file teks bernama:

/etc/ansible/hosts

dengan konten yang terlihat seperti:

[webhosts]
web[1-8]

Ini akan menentukan bahwa mesin "web1, web2 ... web8" berada dalam grup "webhosts". Maka Anda dapat melakukan hal-hal seperti:

ansible webhosts -m service -a "name=apache2 state=restarted" --sudo

untuk me-restart layanan apache2 di semua mesin Anda, menggunakan sudo.

Anda dapat melakukannya dengan perintah cepat seperti:

ansible webhosts -m shell -a "df -h"

atau Anda dapat menjalankan skrip lokal pada mesin jarak jauh:

ansible webhosts -m script -a "./script.sh"

atau Anda dapat membuat buku pedoman (lihat dokumentasi untuk detailnya) dengan konfigurasi lengkap yang Anda inginkan agar sesuai dengan server Anda dan gunakan dengan:

ansible-playbook webplaybook.yml

Pada dasarnya Anda dapat mulai menggunakannya sebagai alat baris perintah untuk menjalankan perintah di beberapa server dan memperluas penggunaannya menjadi alat konfigurasi yang lengkap sesuai keinginan Anda.

seumasmac
sumber
3
Saya suka ansible sebanyak orang berikutnya, tetapi jika dia bertanya tentang sebuah skrip, maka ansible memiliki modul skrip yang sangat bagus :ansible webhosts -m script script.sh
ptman
1
Semua jawaban lainnya melibatkan skrip bash, tapi bukan itu yang dia minta secara spesifik. Dia hanya mengatakan mendorong konfigurasi ke mesin jarak jauh. Tapi disebutkan baik-baik dari modul skrip :)
seumasmac
Silakan pilih jawaban ini! Ini cara untuk melakukannya!
anak ayam
@ptman Saya baru saja memperhatikan bahwa sementara dia tidak menyebutkan skrip dalam pertanyaan, dia melakukannya dalam judul! Maaf. Saya telah memperbarui.
seumasmac
3

Seperti yang dijelaskan dalam jawaban ini, Anda dapat menggunakan heredoc :

ssh user@host <<'ENDSSH'
#commands to run on remote host
ENDSSH

Anda harus berhati-hati dengan heredoc, karena hanya mengirim teks, tetapi tidak benar-benar menunggu respons. Itu berarti tidak akan menunggu perintah Anda dieksekusi.

BЈовић
sumber
1

Jawabannya di sini ( https://stackoverflow.com/a/2732991/4752883 ) berfungsi dengan baik jika Anda mencoba menjalankan skrip pada mesin linux jarak jauh menggunakan plinkatau ssh. Ini akan berfungsi jika skrip memiliki beberapa baris aktif linux.

** Namun, jika Anda mencoba menjalankan skrip batch yang terletak di linux/windowsmesin lokal dan mesin jarak jauh Anda Windows, dan itu terdiri dari beberapa baris menggunakan **

plink root@MachineB -m local_script.bat

itu tidak akan berhasil.

Hanya baris pertama skrip yang akan dieksekusi. Ini mungkin batasan plink.

Solusi 1:

Untuk menjalankan skrip kumpulan multiline (terutama jika relatif sederhana, terdiri dari beberapa baris):

Jika skrip batch asli Anda adalah sebagai berikut

cd C:\Users\ipython_user\Desktop 
python filename.py

Anda dapat menggabungkan garis-garis tersebut menggunakan pemisah "&&" sebagai berikut dalam local_script.batfile Anda sebagai berikut https://stackoverflow.com/a/8055390/4752883 :

cd C:\Users\ipython_user\Desktop && python filename.py

Setelah perubahan ini, Anda kemudian dapat menjalankan skrip seperti yang ditunjukkan di sini oleh @ JasonR.Coombs: https://stackoverflow.com/a/2732991/4752883

Solusi 2:

Jika skrip batch Anda relatif rumit, mungkin lebih baik menggunakan skrip batch yang merangkum perintah plink dan juga seperti yang ditunjukkan di sini oleh @Martin https://stackoverflow.com/a/32196999/4752883 :

rem Open tunnel in the background
start plink.exe -ssh [username]@[hostname] -L 3307:127.0.0.1:3306 -i "[SSH
key]" -N

rem Wait a second to let Plink establish the tunnel 
timeout /t 1

rem Run the task using the tunnel
"C:\Program Files\R\R-3.2.1\bin\x64\R.exe" CMD BATCH qidash.R

rem Kill the tunnel
taskkill /im plink.exe
alpha_989
sumber
0

Mengapa tidak menyalin saja skrip terlebih dahulu, lalu menjalankannya?

scp your_script.sh the_server:
ssh the_server "chmod +x your_script.sh; ./your_script.sh"

Tentu saja Anda harus berhati-hati untuk tidak mengunggahnya ke tempat yang dapat ditulis oleh dunia, sehingga tidak ada orang lain yang bisa bermain dengannya sebelum Anda menjalankannya (mungkin sebagai root).

Dave Vogt
sumber
1
Alasan saya tidak ingin mengunggah skrip adalah agar skrip tidak harus dikelola dan memiliki risiko yang Anda sebutkan. Juga, bagi saya tampaknya lebih sederhana daripada proses multi-langkah mengunggah, memproses, dan (opsional) menghapus.
tremoloqui
0

Menulis ulang script dengan cara yang setiap perintah di dalamnya sudah yang diawali dengan ssh dan hostname / ip atau daftar tersebut akan diteruskan ke script sebagai argumen (dengan asumsi Anda memiliki passwordless / ssh-agent otentikasi kunci mengatur). Beberapa pekerjaan mungkin diperlukan untuk dengan benar melewati kode kesalahan / kembali dari perintah jarak jauh ....

pemeras
sumber
0

Jika skrip tidak terlalu besar, dan Anda menggunakan bash atau ksh ...

ssh vm24 -t bash -c "$(printf "%q" "$(< shell-test.sh )")"

Baik stdin dan stdout bekerja dengan benar tetapi skrip terbatas pada ukuran argumen (biasanya sekitar 100rb). Argumen untuk skrip dapat berfungsi, di akhir baris, mungkin mengikuti argumen "-" tambahan. "-T" untuk mengalokasikan pty adalah opsional.

Hati-hati: Ini membingungkan penyelesaian-bash, jangan tekan tab.

pengguna3710044
sumber