Jalankan perintah jarak jauh, sepenuhnya terlepas dari koneksi ssh

48

Saya punya 2 komputer, localpcdan remoteserver.

Saya perlu localpcmenjalankan beberapa perintah remoteserver. Salah satu hal yang perlu dilakukan adalah memulai skrip cadangan yang berjalan selama beberapa jam. Saya ingin perintah localpcuntuk "menembak" dan kemudian menjalankan sepenuhnya independen remoteserver, seperti localpctidak pernah ada di tempat pertama.

Inilah yang telah saya lakukan sejauh ini:

remoteserver mengandung memiliki skrip:

/root/backup.sh

localpc dijadwalkan untuk menjalankan ini:

ssh root@remoteserver 'nohup /root/backup.sh' &

Apakah saya melakukan ini dengan cara yang benar? Apakah ada cara yang lebih baik untuk melakukan ini? Apakah saya akan mengalami kesulitan melakukannya dengan cara ini?

LVLAaron
sumber
stackoverflow.com/questions/19996089/... dan stackoverflow.com/questions/29142/… memberikan sejumlah pendekatan yang berguna untuk masalah ini tidak menggunakan layar / tmux dll ...
Paul

Jawaban:

47

Anda mungkin harus menggunakan screenpada host jarak jauh, untuk memiliki perintah terpisah nyata:

ssh root@remoteserver screen -d -m ./script
enzotib
sumber
Aku suka ide ini. Ketika skrip selesai, layar akan tetap berjalan ... dan saya harus menghubungkan kembali entah bagaimana nanti lain kali saya ingin menjalankannya, kan?
LVLAaron
@AaronJAnderson: tidak, mengingat bahwa perintah itu bukan shell, ketika itu berakhir juga bahwa sesi layar berakhir.
enzotib
52

Tutup, tapi tidak persis.

Secara independen dari terminal apa pun

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

Anda harus menutup semua deskriptor file yang terhubung ke soket ssh, karena sesi ssh tidak akan ditutup selama beberapa proses jarak jauh membuka soket. Jika Anda tidak tertarik dengan output skrip (mungkin karena skrip itu sendiri mengurus penulisan ke file log), arahkan kembali ke /dev/null(tetapi perhatikan bahwa ini akan menyembunyikan kesalahan seperti tidak dapat memulai skrip).

Penggunaan nohuptidak memiliki efek yang berguna di sini. nohupmengatur program yang dijalankannya untuk tidak menerima sinyal HUP jika terminal pengendali program menghilang, tetapi di sini tidak ada terminal sejak awal, jadi tidak ada yang akan mengirim SIGHUP ke proses secara tiba-tiba. Juga, nohupmengarahkan ulang output standar dan kesalahan standar (tetapi bukan input standar) ke file, tetapi hanya jika mereka terhubung ke terminal, yang, sekali lagi, mereka tidak.

Melepaskan dari terminal

 aaron@localpc$ ssh root@remoteserver
 root@remoteserver# nohup /root/backup.sh </dev/null &
 nohup: appending output to `nohup.out'
 [1] 12345
 root@remoteserver# exit
 aaron@localpc$ 

Gunakan nohupuntuk melepaskan skrip dari terminal pengendali sehingga tidak menerima SIGHUP saat terminal hilang. nohupjuga mengalihkan keluaran standar skrip dan kesalahan standar ke file yang dipanggil nohup.outjika mereka terhubung ke terminal; Anda harus mengurus sendiri input standar.

Menyimpan terminal jarak jauh

Jika Anda ingin agar perintah tetap berjalan di terminal jarak jauh tetapi tidak memilikinya melekat pada sesi SSH, jalankan di terminal multiplexer seperti Layar atau Tmux .

ssh root@remoteserver 'screen -S backup -d -m /root/backup.sh'

Anda nanti dapat menyambung kembali ke terminal tempat skrip berjalan dengan memanggil screen -S backup -rdsebagai root pada mesin itu.

Mengotomatiskan satu perintah jarak jauh

Untuk keamanan yang sedikit lebih baik, jangan membuka login root jarak jauh langsung terlalu banyak. Buat pasangan kunci tujuan khusus dan berikan perintah paksa /root/.ssh/authorized_keys. Isi file kunci publik adalah AAAA…== [email protected]; tambahkan daftar opsi command="…"yang dipisahkan koma termasuk yang menentukan bahwa kunci hanya dapat digunakan untuk menjalankan perintah khusus ini. Pastikan untuk menyimpan semua opsi dan kunci pada satu baris.

command="/root/backup.sh </dev/null >/dev/null 2>/dev/null &",no-port-forwarding,no-agent-forwarding,no-x11-forwarding,no-pty,no-user-rc AAAA…== [email protected]
Gilles 'SANGAT berhenti menjadi jahat'
sumber
Saya telah mencoba perintah pertama yang Anda daftarkan. Itu tidak latar belakang pada kotak yang menjalankan perintah. Kursor hanya duduk di sana dan menunggu untuk selesai ... mungkin itu bug?
LVLAaron
Anda mungkin perlu mengarahkan ulang stdin ke / dev / null pada sistem jarak jauh. Mungkin itulah sebabnya ssh tidak keluar.
KeithB
Saya akan menambahkan -fopsi untuk mendapatkan ssh ke 'latar belakang' (yaitu mengakhiri, menutup koneksi) di sisi lokal. Ini akan bekerja bersama dengan &. nohupopsional dalam kasus ini, tetapi Anda dapat mempertimbangkan untuk menggunakannya setsid.
Alexios
@KeithB Mengarahkan stdin adalah bagian dari itu, tetapi saya juga perlu mengarahkan ulang stdout dan stderr: nohup tidak akan melakukannya di sini karena mereka bukan terminal, dan sebenarnya nohup tidak berguna di sini.
Gilles 'SO- stop being evil'
1
@erikbwork Harap dicatat bahwa saya sama sekali tidak tahu tentang hal-hal itu, tetapi mengikuti diskusi dan komentar: Gilles tidak menggunakan opsi -t dalam perintahnya, jadi tidak ada terminal pseudo yang akan dibuat, baik di klien maupun di server sisi. Karenanya, tidak ada HUP yang akan dikirim.
Binarus
12

Resep standar untuk menjalankan perintah jarak jauh dari login jarak jauh seperti SSH adalah sebagai berikut:

nohup command </dev/null >command.log 2>&1 &

Jika commandadalah skrip shell yang menangani pembuatan log ke file itu sendiri, maka Anda dapat mengubahnya command.logmenjadi /dev/null. Setelah Anda memulai ini, keluarlah segera.

Anda membutuhkan semua yang ada di garis itu.

nohup memberitahu shell untuk tidak mengganggu proses jika sesi login terputus.

</dev/null mengatakan itu tidak pernah menunggu input

>command.log memintanya untuk mengirim pesan apa pun ke file log bernama ini

2>&1memintanya untuk mengirim pesan stderr ke file log yang sama. Dalam beberapa kasus lebih baik memiliki dua file, yang kedua untuk mengumpulkan pesan kesalahan, dan yang pertama untuk mengumpulkan pesan aktivitas normal. Itu dapat membuatnya lebih mudah untuk memverifikasi bahwa semuanya bekerja dengan benar.

& memintanya untuk melepaskan proses ini dan menjalankannya di latar belakang sebagai proses daemon.

Michael Dillon
sumber
10

Utas ini sangat membantu tetapi solusi saya harus sedikit berbeda.

Saya tidak suka solusi layar karena membiarkan proses layar berjalan yang tidak saya butuhkan. Pengalihan dan nohup digunakan seperti ini:

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

TIDAK bekerja untuk saya ketika digunakan dengan perintah ssh.

Saya membuat skrip wrapper pada mesin remote yang menjalankan skrip aktual. Script wrapper mengatur pengalihan dan nohup. Sesuatu seperti ini:

backupwrapper.sh:
nohup backup.sh > /dev/null 2>&1 &

Kemudian pada mesin klien saya, saya menjalankan (perhatikan tidak ada redirection):

# ssh remotemachine "backupwrapper.sh"
#

Perintah ssh segera kembali, koneksi diakhiri dan skrip dibiarkan berjalan.

rui
sumber
6

Seperti yang dikatakan Nils , itu adalah risiko keamanan untuk memungkinkan root untuk masuk melalui ssh. Dan saya menyarankan agar tidak menjalankan pekerjaan besar pada mesin tanpa log. Jika ada masalah, Anda pasti memiliki beberapa pesan pemecahan masalah. Ada jawaban lain yang menunjukkan cara melakukannya. Namun, inilah cara saya merekomendasikan untuk mencapai apa yang Anda minta. Semuanya dibangun ke sh (1). Tidak perlu layar GNU (meskipun saya pikir itu solusi cerdas). Menambahkan string ini untuk perintah Anda: >&- 2>&- <&- &. >&-berarti stdout dekat. 2>&-berarti stderr dekat. <&-berarti stdin dekat. &berarti dijalankan di latar belakang, mis

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$
tbc0
sumber
0

Anda harus mengaktifkan latar belakang perintah jarak jauh remoteserver. Cara Anda melakukannya akan mengaktifkan ssh-command localpc.

Selain itu, ide yang buruk adalah mengizinkan root-ssh.

Jadi setup on remoteserver: Baris sudoers yang akan dijalankan /root/backup.shsebagai root oleh pengguna backup.

Anda dapat membuat pengguna itu tanpa kata sandi "baik".

Masukkan perintah sudo /root/backup.sh &sebagai perintah ~backup/.ssh/authorized_keys- bersama dengan kunci publik dari localpc(siapa pun yang memicu skrip itu).

Nils
sumber
-1
#screen -d -m -S BACKUP ssh root@remoteserver /root/backup.sh
Killinks
sumber
2
Itu tidak terlalu berguna: jika koneksi SSH mati, stdout dan stderr skrip akan ditutup, yang dapat menyebabkan masalah. Layar harus dijalankan pada mesin jarak jauh (seperti pada jawaban enzotib ).
Gilles 'SANGAT berhenti menjadi jahat'