Uzak komutları yürütün, ssh bağlantısından tamamen ayrıldı


48

2 bilgisayarım var localpcve remoteserver.

localpcBazı komutları çalıştırmam gerekiyor remoteserver. Yapması gereken şeylerden biri, birkaç saat çalışan bir yedekleme betiğini başlatmak. Ben komut istiyorum localpctamamen bağımsız çalışıyor olması ardından “yangın” ve remoteserverbenzeri, localpcilk etapta hiç yoktu.

Şimdiye kadar yaptığım şey bu:

remoteserver betiği var:

/root/backup.sh

localpc Bunu çalıştırmak için planlanmış:

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

Bunu doğru şekilde mi yapıyorum? Bunu yapmanın daha iyi bir yolu var mı? Bu şekilde yapma konusunda herhangi bir sorun yaşar mıyım?


stackoverflow.com/questions/19996089/… ve stackoverflow.com/questions/29142/… ekran / tmux vb. kullanmamak için bu sorun için bir takım faydalı yaklaşımlar sağlayın ...
Paul,

Yanıtlar:


47

Muhtemelen screenuzaktaki bir ana makinede, gerçek bir kopuk komut almak için kullanmalısınız:

ssh root@remoteserver screen -d -m ./script

Bu fikri sevdim. Senaryo bitince ekran hala ilerliyor ... ve bir dahaki sefere çalıştırmak istediğimde bir şekilde tekrar bağlanmak zorunda kalacağım, değil mi?
LVLAaron

@AaronJAnderson: hayır, komutun bir kabuk olmadığı düşünüldüğünde, ekran sonlandırıldığında da sonlandırılır.
enzotib

52

Kapat ama tam olarak değil.

Herhangi bir terminalden bağımsız olarak

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

Ssh soketine bağlı tüm dosya tanımlayıcılarını kapatmanız gerekir, çünkü ssh oturumu bazı uzak işlemler soket açık olduğu sürece kapanmaz. Komut dosyasının çıktısıyla ilgilenmiyorsanız (muhtemelen komut dosyasının kendisi bir günlük dosyasına yazmaya özen gösterdiğinden dolayı), onu yeniden yönlendirin /dev/null(ancak komut dosyasının başlatılamaması gibi hataları gizleyeceğini unutmayın).

Kullanmanın nohupburada hiçbir faydası yoktur. nohupProgramın kontrol terminali kaybolursa, programın HUP sinyali almaması için çalışır, ancak burada ilk etapta terminal yoktur, bu nedenle hiçbir şey mavi olmayan sürece bir SIGHUP göndermez. Ayrıca, nohupstandart çıktıyı ve standart hatayı (ancak standart girdiyi) bir dosyaya yönlendirir, ancak yalnızca bir terminale bağlılarsa, ki bunlar tekrar değil.

Terminalden ayırma

 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$ 

nohupKomut dosyasını kontrol terminalinden ayırmak için kullanın , böylece terminal kaybolduğunda SIGHUP alamaz . nohupAyrıca betiğin standart çıktısını ve standart hatasını nohup.out, terminale bağlı ise denilen bir dosyaya yönlendirir ; standart girdiyi kendiniz halletmek zorundasınız.

Uzak bir terminal tutmak

Komutun uzak bir terminalde çalışmasını sağlamak ancak SSH oturumuna eklenmesini istemiyorsanız, Ekran veya Tmux gibi bir terminal çoklayıcıda çalıştırın .

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

Daha sonra komut dosyasını çalıştıran terminale screen -S backup -rd, o makineye root olarak çağrı yaparak yeniden bağlanabilirsiniz .

Bir uzaktan komutu otomatikleştirme

Biraz daha iyi güvenlik için, doğrudan uzak kök girişlerini çok fazla açmayın. Özel amaçlı bir anahtar çifti oluşturun ve buna zorunlu bir komut verin /root/.ssh/authorized_keys. Genel anahtar dosyasının içeriği AAAA…== wibble@example.com; command="…"Anahtarın yalnızca bu belirli komutu yürütmek için kullanılabileceğini belirten, virgülle ayrılmış seçeneklerin bir listesini ekleyin . Seçenekleri ve anahtarı tek bir satırda tuttuğunuzdan emin olun.

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…== wibble@example.com

İlk listelediğiniz komutu denedim. Komutu yürüten kutuda arka plan oluşturmaz. İmleç sadece orada oturur ve tamamlanmasını bekler ... belki de bir böcek?
LVLAaron

Uzaktaki sistemde stdin'i / dev / null konumuna yönlendirmeniz gerekebilir. Bu yüzden ssh çıkmıyor olabilir.
KeithB

Ben eklersiniz -fyerel tarafta (yani yakın bağlantıları sonlandırmak) 'arka' olarak ssh almak için seçenek. Bu ile birlikte çalışacaktır &. nohupBu durumda isteğe bağlıdır, ancak setsidbunun yerine kullanmayı düşünebilirsiniz .
Alexios

@KeithB Yeniden yönlendirme stdin bunun bir parçası, ancak stdout ve stderr'i de yönlendirmem gerekiyor: nohup burada yapmıyor çünkü terminal değiller, aslında nohup burada kullanışlı değil.
Gilles 'SO- kötülükten vazgeç'

1
@ erikbwork Lütfen bu konular hakkında hiçbir fikrim olmadığını unutmayın, ancak tartışma ve yorumları takip edin: Gilles komutlarında -t seçeneğini kullanmaz, dolayısıyla ne istemcide ne de sunucuda sahte terminal kurulmaz. yan. Bu nedenle, hiçbir HUP gönderilmez.
Binarus

12

SSH gibi uzak bir oturum açma işleminden uzak bir komut çalıştırmak için standart tarif şöyledir:

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

Eğer commandbir dosyaya kendisine günlük ilgilenir bir kabuk, o zaman değişebilir command.logiçin /dev/null. Bunu başlattıktan sonra hemen oturumu kapatın.

Bu hattaki her şeye ihtiyacın var.

nohup oturum açma bağlantısı kesilmişse kabuğa işlemi bozmamasını söyler.

</dev/null asla girdi beklememesini söyler

>command.log bu adlandırılmış günlük dosyasına herhangi bir mesaj göndermesini söyler

2>&1stderr mesajlarını aynı günlük dosyasına göndermesini söyler. Bazı durumlarda, iki dosyanın olması, ikincisi hata mesajlarını, ilkini ise normal aktivite mesajlarını toplamak daha iyidir. Bu, her şeyin doğru çalıştığını doğrulamayı kolaylaştırabilir.

& bu süreci çözmesini ve arka planda bir daemon süreci olarak çalıştırmasını söyler.


10

Bu konu çok yardımcı oldu ama çözümüm biraz farklı olmalıydı.

Ekran çözümünü sevmiyorum çünkü ihtiyaç duymadığım bir ekran işlemi bırakıyor. Bu gibi kullanılan yönlendirmeler ve nohuplar:

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

ssh komutuyla birlikte kullanıldığında benim için çalışmıyorlardı.

Uzaktaki makinede asıl komut dosyasını çalıştıran bir sarmalayıcı komut dosyası oluşturdum. Wrapper betiği yönlendirme ve nohup komutunu ayarlar. Bunun gibi bir şey:

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

Sonra istemci makinemde çalıştırıyorum (yönlendirme yok):

# ssh remotemachine "backupwrapper.sh"
#

Ssh komutu derhal geri döner, bağlantı sonlandırılır ve komut dosyası çalışmaya devam eder.


6

As Nils diyor , bu kök ssh ile giriş yapmak için izin vermek için bir güvenlik riski var. Ve herhangi bir kayda değer bir makinede önemli bir iş yapılmamasını tavsiye ediyorum. Bir şey ters giderse, sorun giderme iletilerinizin olmasını istersiniz. Bunu nasıl yapacağınızı gösteren başka cevaplar da var. Ama işte tam olarak istediğin şeyi yapmayı tavsiye ediyorum. Hepsi sh (1) içine yerleştirilmiş. GNU ekranına gerek yok (bunun akıllıca bir çözüm olduğunu düşünüyorum). Komutunuza bu dizeyi ekleyin: >&- 2>&- <&- &. >&-yakın stdout anlamına gelir. 2>&-yakın stderr demektir. <&-yakın stdin demektir. &arka planda çalıştırmak, örneğin

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

0

Remote komutu açık bırakmalısınız remoteserver. Bunu yapma şekliniz, ssh komutunu açacaktır localpc.

Bunun dışında root-ssh'a izin vermek kötü bir fikirdir.

Böylece kurulum remoteserver: /root/backup.shKullanıcı tarafından root olarak çalışacak bir sudoers satırı backup.

Bu kullanıcıyı "iyi" şifre olmadan yaratabilirsiniz.

Komutu sudo /root/backup.sh &, komut satırına yerleştirin ~backup/.ssh/authorized_keys- ortak anahtarla birlikte localpc(bu komut dosyasını kim tetiklerse).


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.