আমি sudo ওভার ssh ব্যবহার করে যথেচ্ছ জটিল কমান্ডটি চালাতে পারি?


80

আমার একটি সিস্টেম রয়েছে যা আমি কেবলমাত্র আমার ব্যবহারকারীর নাম (মাইউসার) এর অধীনে লগইন করতে পারি, তবে অন্যান্য ব্যবহারকারীর (স্ক্রিপ্টুজার) হিসাবে আমার কমান্ড চালাতে হবে। এখনও অবধি, আমার প্রয়োজনীয় কমান্ডগুলি চালানোর জন্য আমি নিম্নলিখিতটি নিয়ে এসেছি:

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

যাইহোক, আমি যখন আরও জটিল কমান্ড চালানোর চেষ্টা করি, যেমন [[ -d "/tmp/Some directory" ]] && rm -rf "/tmp/Some directory"আমি দ্রুত উদ্ধৃতি দিয়ে সমস্যায় পড়ি। আমি নিশ্চিত না যে আমি কীভাবে এই কমপ্লেক্সটি জটিল কমান্ডটি পাস করতে পারি bash -c, যখন \"ইতিমধ্যে আমি যে কমান্ডটি দিয়ে যাচ্ছি তার সীমানা সীমাবদ্ধ করে (এবং তাই আমি কীভাবে / টিএমপি / কিছু ডিরেক্টরিকে উদ্ধৃত করতে জানি না, যার মধ্যে একটি স্পেস রয়েছে)।

উদ্ধৃতিটি কতটা জটিল / উন্মাদ হোক না কেন, বা এটি কোনও সীমাবদ্ধতার মধ্যে পৌঁছেছি কি না কোনও সাধারণ সমাধান আমাকে কোনও আদেশ দিতে পারছে? অন্যান্য সম্ভাব্য এবং সম্ভবত আরও পঠনযোগ্য সমাধান আছে?


11
$ রিমোটে স্ক্রিপ্ট অনুলিপি করুন এবং তারপরে এটি কার্যকর করুন।
ব্যবহারকারী 9517

এটি কার্যকর হবে, তবে আমি এমন একটি সমাধান খুঁজে পেয়েছি যা কোনও স্ক্রিপ্ট ফাইল পিছনে রাখে না (যদি কিছু ব্যর্থ হয় ইত্যাদি ক্ষেত্রে) কিছুটা পরিষ্কার হয়ে যায়।
২৯ শে

9
প্রতিটি রান শেষে স্ক্রিপ্টটি নিজেই rm করুন
থানাসিক

3
ফ্যাব্রিক fabfile.org ব্যবহার বিবেচনা করুন । আপনাকে জীবনকে আরও সহজ করে তুলতে পারে যদি আপনাকে দূর থেকে অনেকটা sudo করতে হয়।
নিলস টোডটম্যান

2
আপনি যদি উত্তরীয় ইনস্টল করে থাকেন তবে এই কমান্ডটি আপনার ব্যবহারের ক্ষেত্রে ডকুমেন্টেশন দেখায়: উত্তরযোগ্য-ডক স্ক্রিপ্ট
bbaassssiiee

উত্তর:


146

আমি যে কৌশলটি মাঝে মাঝে ব্যবহার করি তা হ'ল কমান্ডগুলি এনকোড করতে বেস 64 ব্যবহার করা এবং এটি অন্য সাইটে বাশ করার জন্য পাইপ করা:

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

এটি কোনও নিরাপদ স্ট্রিংয়ের মধ্যে কোনও কমা, ব্যাকস্ল্যাশ, উদ্ধৃতি এবং ভেরিয়েবল সহ স্ক্রিপ্টটিকে এনকোড করবে এবং এটি অন্য সার্ভারে প্রেরণ করবে। ( -w0লাইন মোড়ানো অক্ষম করা আবশ্যক, যা ডিফল্ট column 76 কলামে ঘটে) অন্যদিকে, $(base64 -d)স্ক্রিপ্টটি ডিকোড করবে এবং কার্যকর করতে বাশকে এটি খাওয়াবে।

স্ক্রিপ্টটি যত জটিল ছিল তা নিয়ে আমি কখনই এটি নিয়ে কোনও সমস্যা পাইনি। পালানোর সমস্যাটি সমাধান করে, কারণ আপনার কোনও কিছুর পালানোর দরকার নেই। এটি দূরবর্তী হোস্টে কোনও ফাইল তৈরি করে না এবং আপনি সহজেই জটিল জটিল স্ক্রিপ্টগুলি চালাতে পারেন।


2
বা এমনকি:ssh user@remotehost "echo `base64 -w0 script.sh` | base64 -d | sudo bash"
নিক্লাস বি।

1
এটি লক্ষণীয় যে বেশিরভাগ ক্ষেত্রে আপনি দ্রুত স্থানান্তর সময়ের জন্য বেস 64 এর জন্য lzop বা gzip প্রতিস্থাপন করতে পারেন। তবে প্রান্তের মামলাও থাকতে পারে। YMMV।
কোডগনোম

1
ভাল দ্রষ্টব্য, তবে এটি যদি কোনও স্ক্রিপ্ট হয় তবে আমি আশা করি না যে কোনও স্থানান্তর কয়েক কেবির চেয়ে বেশি হবে।
থোরিয়ামবিআর

7
এখানেও প্রতিধ্বনির অপ্রয়োজনীয় ব্যবহার রয়েছে। base64 script | ssh remotehost 'base64 -d | sudo bash'যথেষ্ট হবে :)
hobbs

যদিও আমি এই সমাধানটি পরীক্ষা করেছি না, স্ক্রিপ্টের ফলাফল কী আউটপুট দেবে, উদাহরণস্বরূপ স্ট্যাডআউটে 'ইয়ম চেক-আপডেট' বলবে? আমি জিজ্ঞাসা করতে চেয়েছিলাম কারণ কেউ যদি মনে করে আমি স্পষ্টতই কিছু খালি কাজ করছি তবে আমি কিছু জিনিস তুলতে পারি।
সোহম চক্রবর্তী

34

-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

আমি প্রায়শই একটি কাজ করি তা হল ভিএম ব্যবহার এবং :!cat % | ssh -tt somemachineকৌশলটি ব্যবহার ।


3
অবশ্যই :!cat % | (command)হিসাবে :w !(command)বা হিসাবে করা যেতে পারে :!(command) < %
স্কট

2
হ্যাঁ. আমার লাইনটি একটি বিড়ালের অপব্যবহার
moebius_eye

ssh -ttকিছু কমান্ড চালানোর পরে দৌড়ানোর ফলে আমার exit

10

আমি মনে করি সবচেয়ে সহজ সমাধানটি @ থানাসিস্কের মন্তব্যের একটি সংশোধনের মধ্যে রয়েছে।

একটি স্ক্রিপ্ট তৈরি করুন, scpএটি মেশিনে, তারপরে এটি চালান।

rmশুরুতে স্ক্রিপ্টটি নিজেই করুন। শেলটি ফাইলটি খুলেছে, সুতরাং এটি লোড করা হয়েছে, এবং তারপরে সমস্যা ছাড়াই মুছে ফেলা যাবে।

এই ক্রমে জিনিসগুলি করে ( rmপ্রথমত, অন্যান্য জিনিস দ্বিতীয়) এটি এমনকি যখন এটি কোনও সময়ে ব্যর্থ হয় তখনও সরানো হবে।


8

আপনার জন্য ভেরিয়েবলের পালানোর যত্ন নিতে আপনি %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'")"

1
এটি একটি দুর্দান্ত সমাধান। অনুরূপ পরিস্থিতির জন্য আমাকে আসলে প্রিন্টফ ব্যবহার করতে হয়েছিল, তবে আমি এটি সর্বদা ভুলে যাই। এটি পোস্ট করার জন্য ধন্যবাদ :-)
জন এল।

8

ব্যাশে এই জাতীয় কিছু চালানোর জন্য এখানে "সঠিক" (সিনট্যাকটিক) উপায়:

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 দেখুন


5

আপনি কি জানেন যে আপনি sudoআপনাকে এমন শেল দেওয়ার জন্য ব্যবহার করতে পারেন যেখানে আপনি নির্বাচিত ব্যবহারকারী হিসাবে কমান্ড চালাতে পারেন?

-আই, - লগিন

লগইন শেল হিসাবে লক্ষ্য ব্যবহারকারীর পাসওয়ার্ড ডাটাবেস এন্ট্রি দ্বারা নির্দিষ্ট শেলটি চালান। এর অর্থ হ'ল। প্রোফাইল, বা লগিনের মতো লগইন-নির্দিষ্ট সংস্থান ফাইলগুলি শেল দ্বারা পঠিত হবে। যদি একটি কমান্ড নির্দিষ্ট করা থাকে, এটি শেলের -c বিকল্পের মাধ্যমে কার্যকর করার জন্য শেলের কাছে প্রেরণ করা হয়। যদি কোনও কমান্ড নির্দিষ্ট না করা থাকে তবে একটি ইন্টারেক্টিভ শেল কার্যকর করা হয়। sudo শেল চালানোর আগে ব্যবহারকারীর হোম ডিরেক্টরিতে পরিবর্তন করার চেষ্টা করে। কমড ম্যান্ডটি এমন একটি পরিবেশের সাথে চালিত হয় যা ব্যবহারকারীর লগ-ইন করার সময় গ্রহণ করে su sudoers নীতি ব্যবহৃত হয়।


এটি আমার কাছে সুস্পষ্ট সমাধান বলে মনে হচ্ছে। > সুডো
আই-

দূরবর্তী অ্যাক্সেসের ক্ষেত্রে "ssh -t" এর সাথে মিলিত হলে এটি সবচেয়ে ভাল কাজ করে। যা প্রশ্নের অন্তর্ভুক্ত রয়েছে, তবে "আমি এই / পুরো / পৃষ্ঠাটি পড়তে পারি না" লোকদের জন্য পুনরাবৃত্তি করে। :)
ড্যানিসাউয়ার

4

আপনি আপনার স্থানীয় মেশিনে স্ক্রিপ্টটি সংজ্ঞায়িত করতে পারেন এবং তারপরে 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

5
ইউইউওসি আপনি <
ব্যবহারকারী 9517

আপনি অন্তর্ভুক্ত উদাহরণ পরিবর্তন করতে পারেন sudo -u scriptuser? আমি মেশিনে পাইপিং করছি স্ক্রিপ্টে আমার ভেরিয়েবল থাকতে হবে তা বিবেচনা করে কি হেরডোক ব্যবহারযোগ্য হবে?
2'14 ভোর

আমি চেষ্টা করছিলাম: echo "sudo `cat fileForSsh.txt`" | ssh ...তবে আমি পেয়ে যাচ্ছি sudo: sorry, you must have a tty to run sudo
jas_raj

যদিও এই/etc/sudoers ফাইলটি আপনি ফাইলটি পরিবর্তিত করতে
পারলে

1
এটি আমার পক্ষে কাজ করে:ssh -tq user@host "sudo bash -s" < test.sh
এভিডি

3

সহজ এবং সহজ।

ssh ব্যবহারকারী @ সার্ভিডর "বাশ-এস" <স্ক্রিপ্ট.শ


1

আপনি যদি যথেষ্ট পরিমাণে বাশ শেল ব্যবহার করেন তবে আপনি আপনার আদেশগুলি কোনও ফাংশনে রেখে দিতে পারেন এবং সেই ফাংশনটি স্ট্রিং হিসাবে মুদ্রণ করতে পারেন export -p -f function_name। স্ট্রিংয়ের ফলাফলের পরে স্বেচ্ছাসেবী কমান্ড থাকতে পারে যা রুট হিসাবে চালাতে হবে না।

ইউনিক্স.এসইতে আমার উত্তর থেকে পাইপ ব্যবহার করে একটি উদাহরণ :

#!/bin/bash
remote_main() {
   local dest="$HOME/destination"

   tar xzv -C "$dest"
   chgrp -R www-data "$dest"
   # Ensure that newly written files have the 'www-data' group too
   find "$dest" -type d -exec chmod g+s {} \;
}
tar cz files/ | ssh user@host "$(declare -pf remote_main); remote_main"

একটি উদাহরণ যা পুনরুদ্ধার করে লগইন ব্যবহারকারীর জন্য ফাইল সংরক্ষণ করে এবং একটি প্রোগ্রাম ইনস্টল করে একটি রুট:

remote_main() {
    wget https://example.com/screenrc -O ~/.screenrc
    sudo apt-get update && sudo apt-get install screen
}
ssh user@host "$(declare -pf remote_main); remote_main"

আপনি যদি পুরো কমান্ডটি ব্যবহার করে চালাতে চান তবে sudoআপনি এটি ব্যবহার করতে পারেন:

remote_main() {
    wget https://example.com/screenrc -O ~user/.screenrc
    apt-get update && apt-get install screen
}
ssh user@host "$(declare -pf remote_main);
    sudo sh -c \"\$(declare -pf remote_main); remote_cmd\""
# Alternatively, if you don't need stdin and do not want to log the command:
ssh user@host "$(declare -pf remote_main);
    (declare -pf remote_main; echo remote_cmd) | sudo sh"

1

এটির জন্য আমার (সত্যই পরীক্ষিত নয়) ক্রেপীয় সমাধানটি এখানে দেওয়া হল:

#!/usr/bin/env ruby
# shell-escape: Escape each argument.
ARGV.each do|a|
  print " '#{a.gsub("'","\'\\\\'\'")}' "
end

আপনি না করতে পারেন:

ssh -tq myuser@hostname "$(shell-escape sudo -u scriptuser bash -c "$(shell-escape ls -al)")"

পরবর্তী পদক্ষেপটি এমন একটি bettersshস্ক্রিপ্ট তৈরি করা যা ইতিমধ্যে এটি করে:

betterssh -tq myuser@hostname sudo -u scriptuser bash -c "$(shell-escape ls -al)"

1

আপনার মধ্যে যাদের স্ক্রিপ্টে প্যারামিটারগুলি পাস করতে হবে এটি নিম্নলিখিত হিসাবে হওয়া উচিত:

ssh user@remotehost "echo `base64 -w0 script.sh` | base64 -d | sudo bash -s <param1> <param2> <paramN>"

1

প্রথমে একটি স্থানীয় স্ক্রিপ্ট তৈরি করুন এবং তারপরে অনুসরণ কমান্ডটি ব্যবহার করে এটি দূরবর্তীভাবে চালিত করুন:

cat <Local Script.sh> | ssh user@server "cat - | sudo -u <user> /bin/bash"
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.