سؤال كيف يمكنني تشغيل الأوامر المعقدة باستخدام sudo عبر ssh؟


لدي نظام يمكنني تسجيل الدخول إليه فقط تحت اسم المستخدم الخاص بي (myuser) ، ولكن أحتاج إلى تشغيل الأوامر كمستخدم آخر (scriptuser). حتى الآن ، توصلت إلى ما يلي لتشغيل الأوامر التي أحتاجها:

ssh -tq myuser@hostname "sudo -u scriptuser bash -c \"ls -al\""

ومع ذلك ، إذا حاولت تشغيل أمر أكثر تعقيدًا ، مثل [[ -d "/tmp/Some directory" ]] && rm -rf "/tmp/Some directory" أنا بسرعة الدخول في المشاكل مع نقلا. لست متأكدًا من كيفية تمرير هذا الأمر المعقد للمثال bash -c، متى \" بالفعل يحدد حدود الأمر الذي أواجهه (وبالتالي لا أعرف كيف أقتبس / تمة / بعض الدليل ، والذي يتضمن مسافات.

هل هناك حل عام يسمح لي بتمرير أي أمر بغض النظر عن مدى تعقيد / جنون الاقتباس ، أو هل هذا نوع من القيود التي توصلت إليها؟ هل هناك حلول أخرى محتملة وربما أكثر قابلية للقراءة؟


76
2017-09-02 09:21


الأصل


انسخ نص برمجي إلى $ remote ثم نفّذه. - Iain
هذا من شأنه أن يعمل ، ولكن أجد الحل الذي يترك أي ملفات البرامج النصية وراء (في حالة فشل شيء وما إلى ذلك) سيكون أنظف قليلا. - VoY
يكون البرنامج النصي نفسه في نهاية كل تشغيل - thanasisk
النظر في استخدام النسيج fabfile.org. يمكن أن يجعلك الحياة أسهل بكثير إذا كان عليك أن ترضي عن بعد الكثير. - Nils Toedtmann
إذا كان لديك Ansible مثبتًا ، فسيعرض هذا الأمر الوثائق لحالة الاستخدام: ansible-doc script - bbaassssiiee


الأجوبة:


الخدعة التي أستخدمها أحيانًا هي استخدام base64 لترميز الأوامر وتوجيهها إلى bash على الموقع الآخر:

MYCOMMAND=$(base64 -w0 script.sh)
ssh user@remotehost "echo $MYCOMMAND | base64 -d | sudo bash"

سيؤدي هذا إلى تشفير البرنامج النصي ، مع أي فواصل ، وخطوط مائلة عكسية ، وعلامات اقتباس ومتغيرات داخل سلسلة آمنة ، وإرسالها إلى الخادم الآخر. (-w0 مطلوب لتعطيل التفاف الخط ، والذي يحدث في العمود 76 بشكل افتراضي). على الجانب الآخر، $(base64 -d) سيقوم بفك شفرة البرنامج النصي وإطعامها إلى bash ليتم تنفيذها.

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


138
2017-09-02 13:10



او حتى: ssh user@remotehost "echo `base64 -w0 script.sh` | base64 -d | sudo bash" - Niklas B.
تجدر الإشارة إلى أنه في معظم الحالات ، يمكنك استبدال lzop أو gzip لـ base64 لأوقات نقل أسرع. ومع ذلك ، قد تكون هناك حالات حافة. YMMV. - CodeGnome
ملاحظة جيدة ، ولكن إذا كان البرنامج نصيًا ، لا أتوقع أن يكون أي نقل أكثر من بضعة كيلوبايت. - ThoriumBR
هناك استخدام غير مجدي للصدى هنا أيضًا. base64 script | ssh remotehost 'base64 -d | sudo bash' سيكون كافيا :) - hobbs
اختبار اليوم وعملت تماما. شكرا الناس. - Soham Chakraborty


شاهد -tt اختيار؟ إقرأ ال ssh(1) كتيب.

ssh -tt root@host << EOF
sudo some # sudo shouldn't ask for a password, otherwise, this fails. 
lines
of
code 
but be careful with \$variables
and \$(other) \`stuff\`
exit # <- Important. 
EOF

الشيء الوحيد الذي غالبا ما أفعله هو استخدام vim واستخدام :!cat % | ssh -tt somemachine الخدعة.


32
2017-09-02 13:01



بالطبع بكل تأكيد :!cat % | (command) يمكن القيام به :w !(command) أو :!(command) < %. - Scott
نعم فعلا. خطي هو إدمان القطة - moebius_eye


أعتقد أن الحل الأسهل يكمن في تعديل تعليق @ thanasisk.

قم بإنشاء برنامج نصي ، scp على الجهاز ، ثم تشغيله.

لديك السيناريو rm نفسها في البداية. لقد فتحت shell الملف ، لذا تم تحميله ، ومن ثم يمكن إزالته دون مشاكل.

من خلال القيام بأشياء في هذا الترتيب (rm أولا ، أشياء أخرى في الثانية) حتى أنه سيتم إزالته عندما يفشل في مرحلة ما.


9
2017-09-02 11:26





يمكنك استعمال ال %q محدد التنسيق مع printf لرعاية المتغير الهروب من أجلك:

cmd="ls -al"
printf -v cmd_str '%q' "$cmd"
ssh user@host "bash -c $cmd_str"

printf -v يكتب الإخراج إلى متغير (في هذه الحالة ، $cmd_str). أعتقد أن هذا هو أبسط طريقة للقيام بذلك. ليس هناك حاجة لنقل أي ملفات أو ترميز سلسلة الأوامر (بقدر ما أحب الخدعة).

في ما يلي مثال أكثر تعقيدًا يوضح أنه يعمل مع أشياء مثل الأقواس المعقوفة وعلامات العطف أيضًا:

$ ssh user@host "ls -l test"
-rw-r--r-- 1 tom users 0 Sep  4 21:18 test
$ cmd="[[ -f test ]] && echo 'this really works'"
$ printf -v cmd_str '%q' "$cmd"
$ ssh user@host "bash -c $cmd_str"
this really works

أنا لم اختبره مع sudo لكن يجب أن تكون بسيطة مثل:

ssh user@host "sudo -u scriptuser bash -c $cmd_str"

إذا كنت تريد ، يمكنك تخطي خطوة وتجنب إنشاء المتغير الوسيط:

$ ssh user@host "bash -c $(printf '%q' "$cmd")"
this really works

أو حتى تجنب إنشاء متغير تمامًا:

ssh user@host "bash -c $(printf '%q' "[[ -f test ]] && echo 'this works as well'")"

7
2017-09-04 20:10



هذا حل رائع. لقد اضطررت في الواقع إلى استخدام printf من قبل لوضع مماثل ، ولكني دائما أنسى ذلك. شكرا لنشر هذه :-) - Jon L.


إليك الطريقة "الصحيحة" (النحوية) لتنفيذ شيء من هذا القبيل في bash:

ssh user@server "$( cat <<'EOT'
echo "Variables like '${HOSTNAME}' and commands like $( uname -a )"
echo "will be interpolated on the server, thanks to the single quotes"
echo "around 'EOT' above.
EOT
)"

ssh user@server "$( cat <<EOT
echo "If you want '${HOSTNAME}' and $( uname -a ) to be interpolated"
echo "on the client instead, omit the the single quotes around EOT."
EOT
)"

للحصول على شرح واف عن كيفية عمل هذا ، يرجى الاطلاع https://stackoverflow.com/a/21761956/111948


6
2018-05-28 17:48





هل أنت على علم أنه يمكنك استخدامها sudo لمنحك shell حيث يمكنك تشغيل الأوامر كمستخدم مختار؟

-i ، --log

تشغيل shell المحدد بواسطة إدخال قاعدة بيانات كلمة مرور المستخدم المستهدف كدليل تسجيل دخول. هذا يعني أن ملفات الموارد الخاصة بتسجيل الدخول مثل                    .profile أو .login سيتم قراءتها بواسطة shell. إذا تم تحديد أمر ، يتم تمريره إلى shell للتنفيذ من خلال الخيار c لـ shell. إذا لا                    يتم تحديد الأمر ، يتم تنفيذ shell التفاعلي. يحاول sudo التغيير إلى الدليل الرئيسي لهذا المستخدم قبل تشغيل shell. كوم-                    يتم تشغيل mand مع بيئة مشابهة لتلك التي يتلقاها المستخدم عند تسجيل الدخول. قسم بيئة الأمر في sudoers (5) docu‐ manual                    كيف يؤثر الخيار -i على البيئة التي يتم فيها تشغيل الأمر عند استخدام سياسة sudoers.


4
2017-09-03 09:22



هذا يبدو وكأنه الحل الواضح بالنسبة لي. > sudo -i -u brian - code_monk
يعمل هذا بشكل أفضل عند الدمج مع "ssh -t" في حالة الوصول عن بعد. والذي تم تضمينه في السؤال ، ولكن مع تكرار لـ "لا يمكنني قراءة هذه الصفحة / بأكملها / الصفحة". :) - dannysauer


يمكنك تحديد البرنامج النصي على جهازك المحلي ومن ثم cat وتوجيهها إلى الجهاز البعيد:

user@host:~/temp> echo "echo 'Test'" > fileForSsh.txt
user@host:~/temp> cat fileForSsh.txt | ssh localhost

Pseudo-terminal will not be allocated because stdin is not a terminal.
stty: standard input: Invalid argument
Test

3
2017-09-02 09:39



UUOC يمكنك استخدام < - Iain
يمكنك تعديل المثال لتشمل sudo -u scriptuser؟ هل سيكون من الممكن أن تكون السلالة الوراثية قابلة للاستخدام نظرًا لأنني بحاجة إلى متغيرات في النص البرمجي ، فهل أقوم بتوصيل الجهاز إلى الجهاز؟ - VoY
كنت أحاول: echo "sudo `cat fileForSsh.txt`" | ssh ... لكنني مستمر في الحصول عليها sudo: sorry, you must have a tty to run sudo. - jas_raj
برغم من هذا السؤال قد يساعد إذا كنت تستطيع الحصول على /etc/sudoers تغير الملف - jas_raj
هذا يعمل بالنسبة لي: ssh -tq user@host "sudo bash -s" < test.sh - AVee


بسيطة وسهلة.

ssh user @ servidor "bash -s" <script.sh


1
2017-09-03 20:15