الحصول على ssh لتنفيذ أمر في الخلفية على الجهاز المستهدف

StackOverflow https://stackoverflow.com/questions/29142

  •  09-06-2019
  •  | 
  •  

سؤال

هذا سؤال متابعة لـ كيف يمكنك استخدام ssh في برنامج نصي شل؟ سؤال.إذا كنت أرغب في تنفيذ أمر على الجهاز البعيد الذي يعمل في الخلفية على ذلك الجهاز، فكيف يمكنني الحصول على أمر ssh للعودة؟عندما أحاول تضمين علامة الضم (&) في نهاية الأمر، يتم تعليقها فقط.يبدو الشكل الدقيق للأمر كما يلي:

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

أيه أفكار؟شيء واحد يجب ملاحظته هو أن تسجيلات الدخول إلى الجهاز المستهدف تنتج دائمًا شعارًا نصيًا، وقد قمت بذلك سش تم إعداد المفاتيح بحيث لا تكون هناك حاجة لكلمة مرور.

هل كانت مفيدة؟

المحلول

لقد واجهت هذه المشكلة في برنامج كتبته قبل عام -- وتبين أن الإجابة معقدة إلى حد ما.ستحتاج إلى استخدام nohup بالإضافة إلى إعادة توجيه الإخراج، كما هو موضح في مقالة ويكيبيديا حول nohup, ، تم نسخه هنا لراحتك.

الوظائف الخلفية nohuping هي على سبيل المثال مفيدة عند تسجيل الدخول عبر SSH ، لأن الوظائف الخلفية يمكن أن تتسبب في تعليق القشرة على تسجيل الدخول بسبب حالة السباق [2].يمكن أيضًا التغلب على هذه المشكلة عن طريق إعادة توجيه جميع تدفقات الإدخال/الإخراج الثلاثة:

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

نصائح أخرى

لقد كانت هذه أنظف طريقة للقيام بذلك بالنسبة لي: -

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

الشيء الوحيد الذي يعمل بعد ذلك هو الأمر الفعلي على الجهاز البعيد

إعادة توجيه FD

يحتاج الإخراج إلى إعادة توجيه مع &>/dev/null الذي يعيد توجيه كل من stderr وstdout إلى /dev/null وهو مرادف لـ >/dev/null 2>/dev/null أو >/dev/null 2>&1.

الأقواس

أفضل طريقة هي الاستخدام sh -c '( ( command ) & )' حيث الأمر هو أي شيء.

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

نوهوب شل

يمكنك أيضًا استخدام nohup مباشرةً لتشغيل الصدفة:

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

إطلاق جميل

هناك خدعة أخرى تتمثل في استخدام Nice لتشغيل الأمر/Shell:

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

أردت فقط أن أعرض مثالاً عمليًا يمكنك قصه ولصقه:

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

إذا كنت لا تستطيع/لا تستطيع إبقاء الاتصال مفتوحًا، فيمكنك استخدامه شاشة, ، إذا كان لديك حقوق تثبيته.

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 &

لفصل جلسة الشاشة: السيطرة-أ د

لسرد جلسات الشاشة:

screen -ls

لإعادة ربط الجلسة:

screen -d -r remote-command

لاحظ أن الشاشة يمكنها أيضًا إنشاء أغلفة متعددة داخل كل جلسة.ويمكن تحقيق تأثير مماثل مع com.tmux.

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

لفصل جلسة tmux: السيطرة ب د

لسرد جلسات الشاشة:

tmux list-sessions

لإعادة ربط الجلسة:

tmux attach <session number>

مفتاح التحكم tmux الافتراضي، 'السيطرة ب"، يصعب استخدامه إلى حد ما ولكن هناك العديد من أمثلة تكوينات tmux التي تأتي مع tmux والتي يمكنك تجربتها.

الطريقة الأسرع والأسهل هي استخدام الأمر "at":

ssh user@target "في الوقت الحالي -f /home/foo.sh"

أعتقد أنه سيتعين عليك الجمع بين اثنتين من هذه الإجابات للحصول على ما تريد.إذا استخدمت nohup مع الفاصلة المنقوطة، وقمت بلف كل شيء بين علامتي اقتباس، فستحصل على:

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

والذي يبدو أنه يعمل بالنسبة لي.مع nohup، لا تحتاج إلى إلحاق & بالأمر المراد تشغيله.أيضًا، إذا لم تكن بحاجة إلى قراءة أي من مخرجات الأمر، فيمكنك استخدامه

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

لإعادة توجيه كافة المخرجات إلى /dev/null.

لقد نجح هذا بالنسبة لي في بعض الأحيان:

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

في الواقع، عندما أحتاج إلى تشغيل أمر معقد على جهاز بعيد، أحب أن أضع الأمر في برنامج نصي على الجهاز الوجهة، وأقوم فقط بتشغيل هذا البرنامج النصي باستخدام ssh.

على سبيل المثال:

# simple_script.sh (located on remote server)

#!/bin/bash

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

وبعد ذلك أقوم بتشغيل هذا الأمر على الجهاز المصدر:

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

كنت أحاول أن أفعل نفس الشيء، ولكن مع التعقيد الإضافي الذي كنت أحاول القيام به من Java.لذا، على أحد الأجهزة التي تعمل بنظام Java، كنت أحاول تشغيل برنامج نصي على جهاز آخر، في الخلفية (باستخدام nohup).

من سطر الأوامر، إليك ما نجح:(قد لا تحتاج إلى "-i keyFile" إذا لم تكن بحاجة إليه لنقله إلى المضيف)

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

لاحظ أنه في سطر الأوامر الخاص بي، توجد وسيطة واحدة بعد "-c"، وكلها بين علامتي اقتباس.ولكن لكي يعمل على الجانب الآخر، فإنه لا يزال بحاجة إلى علامات الاقتباس، لذلك اضطررت إلى وضع علامات الاقتباس المفلترة بداخله.

من جافا، إليك ما نجح:

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.

لقد استغرق الأمر بعض التجربة والخطأ حتى ينجح هذا الأمر، ولكن يبدو أنه يعمل بشكل جيد الآن.

يمكنك أن تفعل ذلك مثل هذا ...

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

لقد بدا الأمر مناسبًا جدًا بالنسبة لي أن أحصل على بعيد جلسة tmux باستخدام tmux new -d <shell cmd> بناء الجملة مثل هذا:

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

سيؤدي هذا إلى إطلاق جلسة جديدة على elsewhere سيعود أمر المضيف وSSH الموجود على الجهاز المحلي إلى نظام التشغيل Shell على الفور تقريبًا.يمكنك بعد ذلك الانتقال إلى المضيف البعيد و tmux attach إلى تلك الجلسة.لاحظ أنه لا يوجد شيء يتعلق بتشغيل tmux المحلي، فقط عن بعد!

أيضًا، إذا كنت تريد أن تستمر جلستك بعد انتهاء المهمة، فما عليك سوى إضافة مشغل Shell بعد الأمر، ولكن لا تنس تضمين علامتي الاقتباس:

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

أعتقد أن هذا هو ما تحتاجه:في البداية تحتاج إلى التثبيت sshpass على جهازك.ثم يمكنك كتابة البرنامج النصي الخاص بك:

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

أولا اتبع هذا الإجراء:

قم بتسجيل الدخول على "أ" كمستخدم "أ" وقم بإنشاء زوج من مفاتيح المصادقة.لا تدخل عبارة المرور:

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

استخدم الآن ssh لإنشاء دليل ~/.ssh كمستخدم b على B.(قد يكون الدليل موجودًا بالفعل، وهذا أمر جيد):

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

أخيرًا، قم بإلحاق المفتاح العام الجديد لـ b@B:.ssh/authorized_keys وأدخل كلمة مرور b مرة أخيرة:

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

من الآن فصاعدًا، يمكنك تسجيل الدخول إلى B باسم b من A كرقم بدون كلمة مرور:

a@A:~> ssh b@B

ثم سيعمل هذا دون إدخال كلمة مرور

ssh b@B "cd /some/directory;برنامج للتنفيذ &"

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top