সুডোর সাথে বাশ স্ক্রিপ্ট ফাংশন সম্পাদন করা হচ্ছে


22

আমার কাছে একটি স্ক্রিপ্ট রয়েছে যা বিভিন্ন কিছু করে, যার বেশিরভাগের জন্য কোনও বিশেষ সুযোগের প্রয়োজন হয় না। যাইহোক, একটি নির্দিষ্ট বিভাগ, যা আমি একটি ফাংশনটির মধ্যে রেখেছি, এর রুট সুবিধার দরকার।

আমি পুরো স্ক্রিপ্টটি রুট হিসাবে চালিত হওয়া চাই না এবং আমি স্ক্রিপ্টের মধ্যে থেকে মূল সুবিধার সাথে এই ফাংশনটি কল করতে সক্ষম হতে চাই। পাসওয়ার্ডের প্রয়োজনে প্রম্পট করা কোনও সমস্যা নয় কারণ এটি বেশিরভাগ ক্ষেত্রেই ইন্টারেক্টিভ। যাইহোক, আমি যখন ব্যবহার করার চেষ্টা করি তখন sudo functionxআমি পাই:

sudo: functionx: command not found

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

আমি আমার ফাংশনটি সন্ধান না করে সুডোতে "দৃশ্যমান" করার উপযুক্ত উপায়টি খুঁজে পাচ্ছি, উপযুক্ত ডিরেক্টরিটি খুঁজে না পেয়ে, এবং তারপরে এটি স্ট্যান্ড-অ্যালোন স্ক্রিপ্ট হিসাবে চালিত করার কোনও উপায় আছে কি?

ফাংশনটি নিজেই একটি পৃষ্ঠার প্রায় দীর্ঘ এবং এতে একাধিক স্ট্রিং থাকে, কিছুটি ডাবল-কোটেড এবং কিছু কিছু একক-উদ্ধৃত। এটি মূল স্ক্রিপ্টের অন্যত্র সংজ্ঞায়িত মেনু ফাংশনের উপরও নির্ভর করে।

আমি কেবলমাত্র সুডো যে কোনও ব্যক্তিই এই ফাংশনটি চালাতে সক্ষম হবেন বলে আশা করি, এটি পাসওয়ার্ড পরিবর্তন করা অন্যতম কাজ।


এতে জড়িত বেশ কয়েকটি ফাংশন এটিকে আরও জটিল এবং ব্যর্থতার প্রবণ করে তোলে। আপনাকে এখন মেনু ফাংশনটি কল করতে পারে এবং তাদেরকেও ডেকে declareআনতে পারে এমন সমস্ত ফাংশন সহ এই জাতীয় সমস্ত নির্ভরতা (এবং তাদের সমস্ত নির্ভরতা খুব বেশি, যদি অনেক স্তরের গভীর হয়) সন্ধান করতে হবে।
কেস

সম্মত হয়েছি এবং আমাকে কেবল বুলেটটি কামড়তে হবে এবং এটি ভেঙে ফেলতে হবে (এবং এটি যে পথটি চালানো হয়েছিল তা সঠিকভাবে নির্ধারণ করার জন্য আমার যথাসাধ্য চেষ্টা করুন, আরও আশা করি যে এর চেয়ে ভাল বিকল্প কোনও বিকল্প না থাকলে শেষ ব্যবহারকারী ফাইলগুলি সাথে রাখবেন)।
ব্রাইকান

উত্তর:


19

আমি স্বীকার করব যে এটি করার সহজ এবং স্বজ্ঞাত উপায় নেই এবং এটি একটি সামান্য হ্যাকি। তবে, আপনি এটি এর মতো করতে পারেন:

function hello()
{
    echo "Hello!"
}

# Test that it works.
hello

FUNC=$(declare -f hello)
sudo bash -c "$FUNC; hello"

বা আরও সহজভাবে:

sudo bash -c "$(declare -f hello); hello"

এটা আমার জন্য কাজ করে:

$ bash --version
GNU bash, version 4.3.42(1)-release (x86_64-apple-darwin14.5.0)
$ hello
Hello!
$
$ FUNC=$(declare -f hello)
$ sudo bash -c "$FUNC; hello"
Hello!

মূলত, declare -fফাংশনটির বিষয়বস্তু ফিরিয়ে দেবে, যা আপনি পরে bash -cইনলাইনে পাস করবেন ।

আপনি যদি ব্যাশের বাইরের উদাহরণ থেকে সমস্ত ফাংশন রফতানি করতে চান তবে এতে পরিবর্তন FUNC=$(declare -f hello)করুন FUNC=$(declare -f)

সম্পাদন করা

উদ্ধৃতি সম্পর্কে মন্তব্যগুলি সম্বোধনের জন্য, এই উদাহরণটি দেখুন:

$ hello()
> {
> echo "This 'is a' test."
> }
$ declare -f hello
hello ()
{
    echo "This 'is a' test."
}
$ FUNC=$(declare -f hello)
$ sudo bash -c "$FUNC; hello"
Password:
This 'is a' test.

1
এটি কেবল দুর্ঘটনাক্রমে কাজ করে, কারণ echo "Hello!"কার্যকরভাবে একইরূপে echo Hello!(যেমন ডাবল-কোটগুলি এই বিশেষ প্রতিধ্বনি কমান্ডের জন্য কোনও পার্থক্য করে না)। অন্যান্য / বেশিরভাগ পরিস্থিতিতে, ফাংশনে ডাবল-কোটগুলি bash -cকমান্ডটি ভঙ্গ করে ।
কাস

1
এটি মূল প্রশ্নের উত্তর দেয়, সুতরাং আমি যদি এর থেকে ভাল সমাধান না পাই তবে আমি তা গ্রহণ করব। যাইহোক, এটি আমার নির্দিষ্ট ফাংশনটি (আমার সম্পাদনা দেখুন) ভঙ্গ করে কারণ এটি স্ক্রিপ্টের অন্য কোথাও সংজ্ঞায়িত ফাংশনগুলির উপর নির্ভরশীল।
ব্রাইকান

1
আমি আজ বিকেলে কিছু টেস্টিং করেছি (ন্যায়বিচারের bash -xcপরিবর্তে ব্যবহার করে bash -c) এবং দেখে মনে bashহচ্ছে এই পরিস্থিতিতে জিনিসগুলিকে পুনরায় উদ্ধৃতি দেওয়ার পক্ষে যথেষ্ট স্মার্ট, এমনকি একক উদ্ধৃতিতে ডাবল-কোটগুলি প্রতিস্থাপন এবং প্রয়োজনে পরিবর্তিত 'করার পরিমাণ পর্যন্ত '\''। আমি নিশ্চিত সেখানে কিছু কিছু ক্ষেত্রে এটা হ্যান্ডেল করতে পারে না হতে হবে, কিন্তু এটা স্পষ্টভাবে অন্তত সহজ এবং পরিমিতরূপে জটিল ক্ষেত্রে জন্য কাজ করে - যেমন করে দেখুনfunction hello() { filename="this is a 'filename' with single quotes and spaces" ; echo "$filename" ; } ; FUNC=$(declare -f hello) ; bash -xc "$FUNC ; hello"
CA গুলির

4
@ ক্যাস declare -fফাংশন সংজ্ঞাটি এমনভাবে মুদ্রণ করে যা বাশের মাধ্যমে পুনরায় পার্স করা যায়, সুতরাং সঠিকভাবে কাজ bash -c "$(declare -f)" করে (ধরে নেওয়া বাহ্যিক শেলটিও বশ । আপনার পোস্ট করা উদাহরণটি এটি সঠিকভাবে কাজ করে দেখায় - যেখানে কোট পরিবর্তন করা হয়েছিল তা ট্রেস-এ রয়েছে , কারণ বাশ শেল সিনট্যাক্সের চিহ্নগুলি bash -xc 'echo "hello world"'
ছাপায়

3
দুর্দান্ত উত্তর। আমি আপনার সমাধানটি বাস্তবায়িত করেছি - আমি নোট করব যে আপনি স্ক্রিপ্টের মধ্যে থেকে নিজেই স্ক্রিপ্টটি আমদানি করতে পারবেন, আপনি যদি শর্তযুক্ত অবস্থায় এটি নীড় sudo yourFunction
বাঁধেন

5

"সমস্যা" হ'ল sudoপরিবেশটি সাফ করে দেয় (মুষ্টিমেয় কয়েকটি অনুমোদিত ভেরিয়েবল ব্যতীত) এবং সুরক্ষা ঝুঁকির বিরুদ্ধে সুরক্ষার জন্য কিছু পরিবর্তনশীল পূর্বনির্ধারিত নিরাপদ মানগুলিতে সেট করে। অন্য কথায়, এটি আসলে কোনও সমস্যা নয়। এটি একটি বৈশিষ্ট্য।

উদাহরণস্বরূপ, আপনি যদি PATH কে প্রাক-সংজ্ঞায়িত মান হিসাবে সেট PATH="/path/to/myevildirectory:$PATH"এবং সেট sudoনা করে থাকেন তবে যে কোনও স্ক্রিপ্ট এটি ব্যবহার করে এমন সমস্ত কমান্ডের (যেমন বেশিরভাগ স্ক্রিপ্টগুলি) পুরো পথের নামটি নির্দিষ্ট করে না /path/to/myevildirectoryঅন্য কোনও ডিরেক্টরিতে প্রদর্শিত হবে। মত রাখুন কমান্ড lsবা grepসেখানে বা অন্যান্য সাধারণ সরঞ্জাম ও আপনি সহজেই সিস্টেমে মত যাই হোক না কেন আপনি কি করতে পারেন।

সবচেয়ে সহজ / সর্বোত্তম উপায় হ'ল ফাংশনটিকে স্ক্রিপ্ট হিসাবে পুনরায় লিখুন এবং এটিকে কোথাও কোথাও সংরক্ষণ করুন (অথবা sudoকমান্ড লাইনের স্ক্রিপ্টের পুরো পথটি নির্দিষ্ট করুন - যা আপনাকে sudoঅনুমতি দেওয়ার জন্য কনফিগার না করা থাকলে আপনাকে যেভাবেই করতে হবে) কোনও কমান্ডকে রুট হিসাবে চালানো), এবং এটি দিয়ে কার্যকর করা যায়chmod +x /path/to/scriptname.sh

স্ক্রিপ্ট হিসাবে শেল ফাংশনটি পুনরায় লেখাই ফাংশন সংজ্ঞাটির ভিতরে থাকা কমান্ডগুলি কোনও ফাইলের (যেমন function ..., {এবং }লাইনগুলি ছাড়াই ) সংরক্ষণ করার মতোই সহজ ।


এটি কোনওভাবেই প্রশ্নের উত্তর দেয় না। তিনি বিশেষত এটিকে কোনও স্ক্রিপ্টে এড়াতে চান।
উইল

1
এছাড়াও sudo -Eপরিবেশ ক্লিয়ারিং এড়াতে।
উইল

আমি কেন কিছুটা হলেও বুঝতে পারি। আমি আশা করছিলাম এই আচরণটি সাময়িকভাবে ওভাররাইড করার কিছু উপায় ছিল। অন্য কোথাও একটি -E বিকল্প উল্লেখ করা হয়েছিল, যদিও এটি এই ক্ষেত্রে কাজ করে না। দুর্ভাগ্যক্রমে, আমি কীভাবে এটি একটি স্বতন্ত্র লিপি তৈরি করতে পারি তার ব্যাখ্যাটির প্রশংসা করি, যা বিশেষত প্রশ্নের উত্তর দেয় না, কারণ আমি এড়াতে চাইতাম কোনও উপায়। শেষ ব্যবহারকারী স্ক্রিপ্টটি কোথায় রাখে সে সম্পর্কে আমার কোনও নিয়ন্ত্রণ নেই এবং মূল স্ক্রিপ্টটি কোথা থেকে চালিত হয়েছে তা সঠিকভাবে নির্ধারণ করার চেষ্টা করে আমি হার্ড-কোডেড ডিরেক্টরি এবং গান এবং নৃত্য উভয়ই এড়িয়ে যেতে চাই।
ব্রাইকান

ওপি এর জন্য যা চেয়েছিল তা কি তা বিবেচনাধীন নয়। তিনি যা চান তা যদি কাজ করে না বা কেবলমাত্র অত্যন্ত সুরক্ষিত কিছু করে কাজ করার জন্য তৈরি করা যেতে পারে তবে তাদের তা জানাতে হবে এবং একটি বিকল্প সরবরাহ করা দরকার - এমনকি যদি বিকল্পটি তারা স্পষ্টভাবে বলেছিল যে তারা চায় না (কারণ কারণ কখনও কখনও এটি নিরাপদে এটি করার একমাত্র বা সর্বোত্তম উপায়)। কাউকে তাদের পায়ে বন্দুকের ইশারা দেওয়ার এবং ট্রিগারটি টান দেওয়ার সম্ভাব্য পরিণতি সম্পর্কে সতর্ক না করে কীভাবে নিজেকে পায়ে গুলি করা উচিত তা বলা বেআইনী হবে।
কেস

1
@ কেস এটি সত্য। এটি নিরাপদে করা যায় না কিছু পরিস্থিতিতে এটি একটি গ্রহণযোগ্য উত্তর। যদিও আমার শেষ সম্পাদনাটি দেখুন। সুরক্ষা সম্পর্কিত প্রভাবগুলির বিষয়ে আপনার মতামত একইভাবে দেওয়া হয়েছে কিনা তা জানতে আমি আগ্রহী।
BryKKan

3

আমি এটি করতে আমার নিজের Sudoবাশ ফাংশনটি লিখেছি , এটি ফাংশন এবং উপস্বকে কল করতে কাজ করে:

function Sudo {
        local firstArg=$1
        if [ $(type -t $firstArg) = function ]
        then
                shift && command sudo bash -c "$(declare -f $firstArg);$firstArg $*"
        elif [ $(type -t $firstArg) = alias ]
        then
                alias sudo='\sudo '
                eval "sudo $@"
        else
                command sudo "$@"
        fi
}

2

আপনি ফাংশন এবং উপকরণ একত্রিত করতে পারেন

উদাহরণ:

function hello_fn() {
    echo "Hello!" 
}

alias hello='bash -c "$(declare -f hello_fn); hello_fn"' 
alias sudo='sudo '

তারপর sudo helloকাজ করে


1

উইলের উত্তরের এখানে একটি পার্থক্য । এটি একটি অতিরিক্ত catপ্রক্রিয়া জড়িত , কিন্তু হেরডোক আরাম দেয়। সংক্ষেপে এটি এর মতো হয়:

f () 
{
    echo ok;
}

cat <<EOS | sudo bash
$(declare -f f)
f
EOS

যদি আপনি চিন্তার জন্য আরও খাদ্য চান তবে এটি চেষ্টা করুন:

#!/bin/bash

f () 
{ 
    x="a b"; 
    menu "$x"; 
    y="difficult thing"; 
    echo "a $y to parse"; 
}

menu () 
{
    [ "$1" == "a b" ] && 
    echo "here's the menu"; 
}

cat <<EOS | sudo bash
$(declare -f f)
$(declare -f menu)
f
EOS

আউটপুটটি হ'ল:

here's the menu
a difficult thing to pass

এখানে আমরা menuপ্রশ্নের একটিটির সাথে সঙ্গতিপূর্ণ ফাংশনটি পেয়েছি , যা "মূল স্ক্রিপ্টের অন্যত্র সংজ্ঞায়িত"। "অন্য কোথাও" এর অর্থ যদি এই পর্যায়ে তার সংজ্ঞাটি ইতিমধ্যে পঠিত হয়েছে যখন দাবি sudoকরা ফাংশনটি সম্পাদন করা হচ্ছে তখন পরিস্থিতি সাদৃশ্যপূর্ণ। তবে এটি এখনও পড়া হয়নি। আরও একটি ফাংশন থাকতে পারে যা তার সংজ্ঞাটি এখনও ট্রিগার করবে। এই ক্ষেত্রে declare -f menuআরও পরিশীলিত কিছু দিয়ে প্রতিস্থাপন করতে হবে, বা পুরো স্ক্রিপ্টটি এমনভাবে সংশোধন করা হয়েছে যাতে menuফাংশনটি ইতিমধ্যে ঘোষিত হয়েছে।


অনেক আগ্রহব্যাঞ্জক. আমি এটি একটি সময়ে চেষ্টা করে দেখতে হবে। এবং হ্যাঁ, menuফাংশনটি এই বিন্দুটির আগে ঘোষণা করা হত, যেমন fএকটি মেনু থেকে আহবান করা হয়।
ব্রিককান

0

আপনার স্ক্রিপ্টটি হয় (ক) স্ব-অন্তর্ভুক্ত বা (খ) এর অবস্থানের ভিত্তিতে এর উপাদানগুলি উত্স করতে পারে (আপনার বাড়ির ডিরেক্টরিটি কোথায় রয়েছে তা স্মরণ করার চেয়ে), আপনি এরকম কিছু করতে পারেন:

  • কমান্ডটিতে $0এটি ব্যবহার করে স্ক্রিপ্টের জন্য পাথের নামটি ব্যবহার করুন sudoএবং পাসওয়ার্ড আপডেটিংকে কল করতে স্ক্রিপ্ট যাচাই করবে এমন একটি বিকল্প দিয়ে দিন। আপনি যতক্ষণ পাথের স্ক্রিপ্টটি সন্ধানের উপর নির্ভর করছেন (কেবল চালানোর পরিবর্তে ./myscript) আপনার একটি নিখুঁত পথের নাম পাওয়া উচিত $0
  • যেহেতু sudoস্ক্রিপ্টটি চালায়, স্ক্রিপ্টে এটি প্রয়োজনীয় ফাংশনগুলিতে এটির অ্যাক্সেস রয়েছে ।
  • স্ক্রিপ্টের শীর্ষে (পরিবর্তে, ফাংশন ঘোষণার পূর্বে) স্ক্রিপ্টটি এটি পরীক্ষা করে uidবুঝতে পারে যে এটি রুট ব্যবহারকারী হিসাবে চালিত হয়েছিল এবং এটি পাসওয়ার্ড আপডেট করার জন্য এটি বলার জন্য বিকল্প সেট রয়েছে তা দেখে যান এবং করুন যে।

বিভিন্ন কারণে স্ক্রিপ্টগুলি পুনরাবৃত্তি করতে পারে: সুযোগ সুবিধাগুলি পরিবর্তনের মধ্যে একটি।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.