Mendapatkan ssh untuk menjalankan perintah di latar belakang pada mesin target


304

Ini adalah pertanyaan lanjutan untuk Bagaimana Anda menggunakan ssh dalam skrip shell? pertanyaan. Jika saya ingin menjalankan perintah pada mesin jarak jauh yang berjalan di latar belakang pada mesin itu, bagaimana cara mendapatkan perintah ssh untuk kembali? Ketika saya mencoba untuk hanya memasukkan ampersand (&) di akhir perintah itu hanya hang. Bentuk persisnya dari perintah ini terlihat seperti ini:

ssh user@target "cd /some/directory; program-to-execute &"

Ada ide? Satu hal yang perlu diperhatikan adalah bahwa login ke mesin target selalu menghasilkan spanduk teks dan saya memiliki kunci SSH yang diatur sehingga tidak diperlukan kata sandi.

Jawaban:


315

Saya memiliki masalah ini dalam program yang saya tulis setahun yang lalu - ternyata jawabannya agak rumit. Anda harus menggunakan nohup dan juga pengalihan output, seperti yang dijelaskan di wikipedia artcle di nohup , disalin di sini untuk kenyamanan Anda.

Pekerjaan latar belakang non-aktifkan misalnya berguna ketika masuk melalui SSH, karena pekerjaan latar belakang dapat menyebabkan shell untuk hangout karena kondisi lomba [2]. Masalah ini juga dapat diatasi dengan mengarahkan ulang ketiga aliran I / O:

nohup myprogram > foo.out 2> foo.err < /dev/null &

1
File-file itu dibuat di direktori saat ini. Jadi batasnya adalah jumlah ruang kosong pada partisi. Tentu saja Anda juga dapat mengalihkan ke /dev/null.
Frank Kusters

2
Adakah ide tentang latar belakang proses setelah selesai meminta konfirmasi? (seperti gpg --decrypt yang sudah selesai meminta kata sandi)
isaaclw

Mencoba memulai pekerja resque di latar belakang menggunakan nohup, tetapi tidak berhasil; :(
Infant Dev

1
Bisakah Anda jelaskan apa < /dev/nullartinya? Terima kasih.
Qian Chen

1
Juga dari artikel wikipedia di nohup: "Perhatikan juga bahwa sesi penutupan SSH tidak selalu mengirim sinyal HUP ke proses tergantung. Antara lain, ini tergantung pada apakah terminal semu dialokasikan atau tidak." Jadi, meskipun benar-benar nohup tidak selalu dibutuhkan, Anda lebih baik untuk jangka panjang daripada tanpa.
Jax

254

Ini telah menjadi cara terbersih untuk melakukannya untuk saya: -

ssh -n -f user@host "sh -c 'cd /whereever; nohup ./whatever > /dev/null 2>&1 &'"

Satu-satunya hal yang berjalan setelah ini adalah perintah aktual pada mesin jarak jauh


7
-ntidak diperlukan seperti -ftersirat-n
blissini

6
ssh -fmembiarkan proses ssh terhubung, hanya dilatar belakangi. Solusi / dev / null memungkinkan ssh untuk memutuskan dengan cepat, yang mungkin lebih disukai.
Beni Cherniavsky-Paskin

Solusi ini juga berfungsi untuk mengirim perintah melalui ssh ke Syonology NAS
Stefan F

Saya perlu hasil "ls-l" untuk muncul di remote saya, perintah ini tidak melakukannya.
Siddharth

@Iddharth Kemudian arahkan ke beberapa file bernama daripada / dev / null.
sherrellbc

29

Redirect fd

Keluaran perlu diarahkan dengan &>/dev/nullpengalihan stderr dan stdout ke / dev / null dan merupakan sinonim dari >/dev/null 2>/dev/nullatau >/dev/null 2>&1.

Paranthes

Cara terbaik adalah menggunakan di sh -c '( ( command ) & )'mana perintah adalah segalanya.

ssh askapache 'sh -c "( ( nohup chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'

Nohup Shell

Anda juga dapat menggunakan nohup secara langsung untuk meluncurkan shell:

ssh askapache 'nohup sh -c "( ( chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'

Peluncuran yang bagus

Trik lain adalah menggunakan nice untuk meluncurkan perintah / shell:

ssh askapache 'nice -n 19 sh -c "( ( nohup chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'

8
Saya tahu ini adalah jawaban Anda yang sangat lama, tetapi bisakah Anda menambahkan beberapa komentar tentang mengapa tanda kurung adalah cara terbaik, apa bedanya menambahkan perbedaan (jika ada) nohup, dan mengapa serta kapan Anda akan menggunakannya nice? Saya pikir itu akan menambah banyak jawaban ini.
Dr K

Mungkin sebagian menjawab ini: Dengan nohup, Anda tidak perlu menambahkan & ke perintah yang akan dijalankan.
Cadoiz

21

Jika Anda tidak / tidak bisa menjaga koneksi tetap terbuka Anda bisa menggunakan layar , jika Anda memiliki hak untuk menginstalnya.

user@localhost $ screen -t remote-command
user@localhost $ ssh user@target # now inside of a screen session
user@remotehost $ cd /some/directory; program-to-execute &

Untuk melepaskan sesi layar: ctrl-a d

Untuk daftar sesi layar:

screen -ls

Untuk memasang kembali sesi:

screen -d -r remote-command

Perhatikan bahwa layar juga dapat membuat beberapa shell dalam setiap sesi. Efek serupa dapat dicapai dengan tmux .

user@localhost $ tmux
user@localhost $ ssh user@target # now inside of a tmux session
user@remotehost $ cd /some/directory; program-to-execute &

Untuk melepaskan sesi tmux: ctrl-b d

Untuk daftar sesi layar:

tmux list-sessions

Untuk memasang kembali sesi:

tmux attach <session number>

Kunci kontrol tmux default, ' ctrl-b', agak sulit digunakan tetapi ada beberapa contoh konfigurasi tmux yang disertakan bersama tmux yang dapat Anda coba.


3
bagaimana orang menggunakannya screenuntuk ini?
Quamis

18

Saya hanya ingin menunjukkan contoh kerja yang dapat Anda potong dan tempel:

ssh REMOTE "sh -c \"(nohup sleep 30; touch nohup-exit) > /dev/null &\""

Sangat membantu. Terima kasih.
Michael Martinez

8

Cara tercepat dan termudah adalah dengan menggunakan perintah 'at':

ssh user @ target "at -f /home/foo.sh"


2
Ini akan menjadi solusi umum yang bagus jika atargumen baris perintah diterima setelah waktu dan tidak hanya dari file.
Tyler Collier

3
Anda dapat mensimulasikan file dengan <<< seperti di: ssh user @ target "at -f <<< 'my_comnads'"
Nico

6

Saya pikir Anda harus menggabungkan beberapa jawaban ini untuk mendapatkan yang Anda inginkan. Jika Anda menggunakan nohup dalam hubungannya dengan titik koma, dan membungkus semuanya dalam tanda kutip, maka Anda mendapatkan:

ssh user@target "cd /some/directory; nohup myprogram > foo.out 2> foo.err < /dev/null"

yang sepertinya bekerja untuk saya. Dengan nohup, Anda tidak perlu menambahkan & ke perintah yang akan dijalankan. Juga, jika Anda tidak perlu membaca output dari perintah, Anda dapat menggunakannya

ssh user@target "cd /some/directory; nohup myprogram > /dev/null 2>&1"

untuk mengarahkan semua output ke / dev / null.


5

Ini bekerja untuk saya mungkin:

ssh -x remoteServer "cd yourRemoteDir; ./yourRemoteScript.sh </dev/null >/dev/null 2>&1 & " 

2

Anda bisa melakukannya seperti ini ...

sudo /home/script.sh -opt1 > /tmp/script.out &

Sempurna, bekerja dengan sesi SST Putty. Saya dapat keluar dan script berlanjut di mesin. Terima kasih.
Satria

1

Sebenarnya, setiap kali saya perlu menjalankan perintah pada mesin jarak jauh yang rumit, saya suka memasukkan perintah ke dalam skrip di mesin tujuan, dan jalankan saja skrip itu menggunakan ssh.

Sebagai contoh:

# simple_script.sh (located on remote server)

#!/bin/bash

cat /var/log/messages | grep <some value> | awk -F " " '{print $8}'

Dan kemudian saya jalankan perintah ini di mesin sumber:

ssh user@ip "/path/to/simple_script.sh"

0

Saya mencoba melakukan hal yang sama, tetapi dengan kompleksitas tambahan yang saya coba lakukan dari Jawa. Jadi pada satu mesin yang menjalankan java, saya mencoba menjalankan skrip di komputer lain, di latar belakang (dengan nohup).

Dari baris perintah, inilah yang bekerja: (Anda mungkin tidak memerlukan "-i keyFile" jika Anda tidak perlu ssh ke host)

ssh -i keyFile user@host bash -c "\"nohup ./script arg1 arg2 > output.txt 2>&1 &\""

Perhatikan bahwa ke baris perintah saya, ada satu argumen setelah "-c", yang semuanya dalam tanda kutip. Tapi agar bisa bekerja di ujung yang lain, masih membutuhkan tanda kutip, jadi saya harus meletakkan tanda kutip lolos di dalamnya.

Dari java, inilah yang berhasil:

ProcessBuilder b = new ProcessBuilder("ssh", "-i", "keyFile", "bash", "-c",
 "\"nohup ./script arg1 arg2 > output.txt 2>&1 &\"");
Process process = b.start();
// then read from process.getInputStream() and close it.

Butuh sedikit percobaan & kesalahan agar ini berfungsi, tetapi tampaknya berfungsi dengan baik sekarang.


0

Tampaknya cukup nyaman bagi saya untuk memiliki sesi tmux jarak jauh menggunakan tmux new -d <shell cmd>sintaks seperti ini:

ssh someone@elsewhere 'tmux new -d sleep 600'

Ini akan meluncurkan sesi baru di elsewherehost dan perintah ssh pada mesin lokal akan kembali ke shell hampir secara instan. Anda kemudian dapat ssh ke host jarak jauh dantmux attach ke sesi itu. Perhatikan bahwa tidak ada apa pun tentang tmux lokal yang berjalan, hanya jarak jauh!

Juga, jika Anda ingin sesi Anda berlanjut setelah pekerjaan selesai, cukup tambahkan peluncur shell setelah perintah Anda, tetapi jangan lupa untuk menyertakan tanda kutip:

ssh someone@elsewhere 'tmux new -d "~/myscript.sh; bash"'

0
YOUR-COMMAND &> YOUR-LOG.log &    

Ini harus menjalankan perintah dan menetapkan id proses yang Anda dapat dengan mudah mengekor-LOG.log ANDA untuk melihat hasil yang tertulis padanya saat terjadi. Anda dapat keluar kapan saja dan proses akan berlanjut


0

Anda dapat melakukan ini tanpa nohup:

ssh user@host 'myprogram >out.log 2>err.log &'

-2

Saya pikir inilah yang Anda butuhkan: Awalnya Anda harus menginstal sshpassdi mesin Anda. maka Anda dapat menulis skrip Anda sendiri:

while read pass port user ip; do
sshpass -p$pass ssh -p $port $user@$ip <<ENDSSH1
    COMMAND 1
    .
    .
    .
    COMMAND n
ENDSSH1
done <<____HERE
    PASS    PORT    USER    IP
      .      .       .       .
      .      .       .       .
      .      .       .       .
    PASS    PORT    USER    IP    
____HERE

-3

Pertama ikuti prosedur ini:

Masuk pada A sebagai pengguna a dan hasilkan sepasang kunci otentikasi. Jangan masukkan frasa sandi:

a@A:~> ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/a/.ssh/id_rsa): 
Created directory '/home/a/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/a/.ssh/id_rsa.
Your public key has been saved in /home/a/.ssh/id_rsa.pub.
The key fingerprint is:
3e:4f:05:79:3a:9f:96:7c:3b:ad:e9:58:37:bc:37:e4 a@A

Sekarang gunakan ssh untuk membuat direktori ~ / .ssh sebagai pengguna b pada B. (Direktori mungkin sudah ada, yang tidak masalah):

a@A:~> ssh b@B mkdir -p .ssh
b@B's password: 

Terakhir, tambahkan kunci publik baru a ke b @ B: .ssh / otor_keys dan masukkan kata sandi b terakhir kali:

a@A:~> cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys'
b@B's password: 

Mulai sekarang Anda dapat masuk ke B sebagai b dari A tanpa kata sandi:

a@A:~> ssh b@B

maka ini akan berfungsi tanpa memasukkan kata sandi

ssh b @ B "cd / some / direktori; program-untuk-mengeksekusi &"


1
Pertanyaannya mengatakan bahwa dagorym sudah mengatur kunci untuk tidak memerlukan kata sandi, tapi masih menggantung
Max Nanasy
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.