শব্দ বিভাজন এড়াতে আমি কীভাবে স্ট্রিংয়ের অভ্যন্তরে একটি পরিবর্তনশীল প্রসারণ উদ্ধৃত করতে পারি?


9
$ myvar="/path to/my directory"
$ sudo bash -c "cd $myvar"

এরকম ক্ষেত্রে, $myvarশব্দের বিভাজন এড়াতে আমি কীভাবে উদ্ধৃতি দিতে পারি কারণ এর মান শ্বেত স্থান আছে myvar?


4
আপনি এটি কীভাবে সমাধান করেন তা বিবেচনা না করে, এটি এখনও খুব বেশি কিছু করবে না। শেলের cdভিতরেই কেবল প্রভাব রয়েছে bash -c
কুসালানন্দ

আমি কেবল প্রশ্নের জন্য কেবলমাত্র একটি ন্যূনতম উদাহরণ দিচ্ছি, এটি আমার আসল সমস্যার সমাধানের সমাধান নয়, যা ইউনিক্স.স্ট্যাকেক্সেঞ্জঞ্জ.com/a/269080/674 প্লাস যে sudo bash -cআমাকে দেওয়া কমান্ড স্ট্রিংয়ে আমার পরিবর্তনশীল প্রসার রয়েছে এমন একটি পাথনাম যার মধ্যে শ্বেতস্পেস থাকতে পারে।
টিম

উত্তর:


13

সেই কোডটিতে কোনও শব্দের বিভাজন নেই (সেই বৈশিষ্ট্যে যা অব্যক্ত বিস্তৃতিতে ভেরিয়েবলগুলি বিভক্ত হয়) যেমনটি $myvarউদ্ধৃত হয়নি।

একটি কমান্ড ইনজেকশন দুর্বলতা যেমন $myvarপাস করার আগে প্রসারিত হয় bash। সুতরাং এর বিষয়বস্তু ব্যাশ কোড হিসাবে ব্যাখ্যা করা হয়!

সেখানে থাকা স্পেসগুলি শব্দের বিভক্তিরcd কারণে নয় , তবে শেল বাক্য গঠনতে বিভিন্ন টোকেন হিসাবে বিভক্ত হবে বলে একাধিক যুক্তি পাঠিয়ে দেবে। এর মান সহ bye;reboot, এটি পুনরায় চালু হবে! ¹

এখানে, আপনি চান:

sudo bash -c 'cd -P -- "$1"' bash "$myvar"

(যেখানে আপনি বিষয়বস্তু পাস $myvarযে ইনলাইন স্ক্রিপ্ট প্রথম আর্গুমেন্ট হিসেবে; নোট কিভাবে উভয় $myvarএবং $1আটকান IFS-শব্দ-বিভাজন (এবং globbing) এর নিজ নিজ শেল জন্য উদ্ধৃত করা হয়েছে)।

বা:

sudo MYVAR="$myvar" bash -c 'cd -P -- "$MYVAR"'

(যেখানে আপনি $myvarপরিবেশের পরিবর্তনশীলের বিষয়বস্তুগুলি পাস করেন )।

অবশ্যই আপনি চালিয়ে দরকারী কিছু অর্জন করা হবে না শুধুমাত্র cd যে ইনলাইন লিপিতে (কিনা চেক ছাড়া অন্য rootকরতে পারেন cdসেখানে প্রবেশ)। সম্ভবত, আপনি সেই স্ক্রিপ্টটি cdসেখানে চান এবং তারপরে সেখানে অন্য কিছু করুন:

sudo bash -c 'cd -P -- "$1" && do-something' bash "$myvar"

যদি অন্যথায় আপনার অ্যাক্সেস না থাকে এমন কোনও ডিরেক্টরিতে sudoসক্ষম হওয়ার উদ্দেশ্যে যদি উদ্দেশ্যটি হয় cdতবে তা সত্যিই কাজ করতে পারে না।

sudo sh -c 'cd -P -- "$1" && exec bash' sh "$myvar"

bashএর বর্তমান ডিরেক্টরিতে একটি ইন্টারেক্টিভ শুরু করবে $myvar। কিন্তু যে শেল হিসাবে চলমান হবে root

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

sudo sh -c 'cd -P -- "$1" && exec sudo -u "$SUDO_USER" bash' sh "$myvar"

bashবর্তমান ডিরেক্টরিটি থাকার সাথে একটি অনিচ্ছাকৃত ইন্টারেক্টিভ পেতে $myvar, তবে যদি আপনাকে cdপ্রথমে সেই ডিরেক্টরিটিতে প্রবেশের অনুমতি না থাকে তবে আপনি যদি বর্তমান ডিরেক্টরিটি তৈরি করেন তখনও আপনি সেই ডিরেক্টরিতে কিছু করতে সক্ষম হবেন না।

$ myvar=/var/spool/cron/crontabs
$ sudo sh -c 'cd -P -- "$1" && exec sudo -u "$SUDO_USER" bash' sh "$myvar"
bash-4.4$ ls
ls: cannot open directory '.': Permission denied

একটি ব্যতিক্রম হ'ল যদি আপনার নিজেরাই ডিরেক্টরিতে অনুসন্ধানের অনুমতি পেয়ে থাকেন তবে এর পথের ডিরেক্টরিগুলির একটিতে না থেকে:

$ myvar=1/2
$ mkdir -p "$myvar"
$ chmod 0 1
$ cd 1/2
cd: permission denied: 1/2
$ sudo sh -c 'cd -P -- "$1" && exec sudo -u "$SUDO_USER" bash' sh "$myvar"
bash-4.4$ pwd
/home/stephane/1/2
bash-4.4$ mkdir 3
bash-4.4$ ls
3
bash-4.4$ cd "$PWD"
bash: cd: /home/stephane/1/2: Permission denied

¹ কড়া কথায় বলতে গেলে (আক্ষরিক) $myvarমতো মানের জন্য শেল $(seq 10)দ্বারা এই কমান্ডের প্রতিস্থাপনের প্রসার ঘটলে শব্দ বিভাজন অবশ্যই হবেbashroot


4

নতুন (বাশ 4.4) উদ্ধৃত যাদু রয়েছে যা আপনাকে আরও সরাসরি যা করতে চান তা করতে দেয়। বৃহত্তর প্রসঙ্গের উপর নির্ভর করে, অন্য একটি কৌশল ব্যবহার করা আরও ভাল হতে পারে, তবে এটি এই সীমিত প্রসঙ্গে কাজ করে।

sudo bash -c "cd ${myvar@Q}; pwd"

4

আপনি যদি এই বিষয়বস্তুতে বিশ্বাস করতে না পারেন $myvarতবে একমাত্র যুক্তিযুক্ত পদ্ধতির হ'ল printfএটির একটি পালানো সংস্করণ তৈরি করতে GNU ব্যবহার করা:

#!/bin/bash

myvar=$(printf '%q' "$myvar")
bash -c "echo $myvar"

printfম্যান পেজ যেমন বলে:

%q

তর্কটি একটি বিন্যাসে মুদ্রিত হয় যা শেল ইনপুট হিসাবে পুনরায় ব্যবহার করা যেতে পারে, প্রস্তাবিত পসিক্স $''সিনট্যাক্সের সাহায্যে মুদ্রণযোগ্য অক্ষরগুলি এড়িয়ে যায় ।


এর একটি বহনযোগ্য সংস্করণের জন্য আমার উত্তর দেখুন।
আর .. গীটহাব বন্ধ করুন আইসিসি

GNU printfকেবল সেখানে GNU সিস্টেমে ডাকা হবে এবং যদি এটি $(printf '%q' "$myvar")কোনও শেলটিতে চালিত হয় যেখানে printfঅন্তর্নির্মিত নয়। printfআজকাল বেশিরভাগ শাঁস তৈরি হয়েছে । %qযদিও সমস্তই সমর্থন করে না এবং যখন তারা করে, তারা সংশ্লিষ্ট শেল দ্বারা সমর্থিত কোনও ফর্ম্যাটে জিনিসটি উদ্ধৃত করবে, যা সম্ভবত বোঝার মতো নয় bash। আসলে, bashএর printfনিজেই এমনকি কিছু মান জন্য সঠিকভাবে কিছু উদ্ধৃত করা ব্যর্থ $myvarকয়েকটি লোকেইলে।
স্টাফেন চেজেলাস

সঙ্গে bash-4.3অন্তত এখনও সঙ্গে কমান্ড ইনজেকশন দুর্বলতার এর myvar=$'\xa3``reboot`\xa3`' একটি zh_HK.big5hkscs উদাহরণস্বরূপ লোকেল।
স্টাফেন চেজেলাস 21

3

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

quote () { printf %s\\n "$1" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/" ; }

এই ফাংশনটি দিয়ে আপনি তা করতে পারেন:

myvar="/path to/my directory"
sudo bash -c "cd $(quote "$myvar")"

3

স্টাফেন চ্যাজেলাস যা পরামর্শ দেয় তা হ'ল এটি করার সর্বোত্তম উপায়। আমি কেবলমাত্র sedআর এর উত্তরগুলির মতো সাব-প্রসেস ব্যবহারের বিপরীতে প্যারামিটার সম্প্রসারণ সিনট্যাক্সের সাথে কীভাবে নিরাপদে উদ্ধৃতি দিতে পারি তার একটি উত্তর সরবরাহ করব '

myvar='foo \'\''"bar'

quote() {
  printf "'%s'" "${1//\'/\'\\\'\'}"
}

printf "value: %s\n" "$myvar"
printf "quoted: %s\n" "$(quote "$myvar")"
bash -c "printf 'interpolated in subshell script: %s\n' $(quote "$myvar")"

এই স্ক্রিপ্টের আউটপুট হল:

value: foo \'"bar
quoted: 'foo \'\''"bar'
interpolated in subshell script: foo \'"bar

1

হ্যাঁ, শব্দ বিভাজন আছে।
ভাল, প্রযুক্তিগতভাবে, কমান্ড লাইন বিভাজন লাইন পার্সিং উপর।

প্রথমে উদ্ধৃতিটি সঠিকভাবে পাওয়া যাক:

কমান্ডটি কার্যকর করার সহজ সমাধানগুলির (এবং অনিরাপদ) সমাধান হিসাবে আমি বিশ্বাস করি আপনি এটি চাইবেন:

bash -c "cd \"$myvar\""

আসুন যা ঘটে তা নিশ্চিত করুন (ধরে নিচ্ছেন myvar="/path to/my directory"):

$ bash -c "printf '<%s>\n' $myvar"
<./path>
<to/my>
<directory>

আপনি দেখতে পাচ্ছেন যে, পথের স্ট্রিংগুলি ফাঁকা জায়গায় বিভক্ত হয়েছিল। এবং:

$ bash -c "printf '<%s>\n' \"$myvar\""
<./path to/my directory>

বিভক্ত হয় না।

তবে, কমান্ডটি (যেমন লিখিত) নিরাপত্তাহীন। আরও ভাল ব্যবহার:

$ bash -c "cd -P -- \"$myvar\"; pwd"
/home/user/temp/path to/my directory

এটি সিডি সুরক্ষিত করবে এমন ফাইলগুলির বিরুদ্ধে যা ড্যাশ (-) দিয়ে শুরু হয় বা নিম্নলিখিত লিঙ্কগুলির ফলে সমস্যার সৃষ্টি হতে পারে।

এটি কাজ করবে যদি আপনি বিশ্বাস করতে পারেন যে স্ট্রিংটি $myvarএকটি পথ।
তবে, "কোড ইঞ্জেকশন" এখনও সম্ভব কারণ আপনি "স্ট্রিং কার্যকর করছেন":

$ myvar='./path to/my directory";date;"true'
$ bash -c "printf '<%s> ' \"$myvar\"; echo"
<./path to/my directory> Tue May  8 12:25:51 UTC 2018

আপনার স্ট্রিংয়ের আরও শক্তিশালী উদ্ধৃতি প্রয়োজন, যেমন:

$ bash -c 'printf "<%s> " "$1"; echo' _ "$myvar"
<./path to/my directory";date -u;"true>

আপনি উপরে দেখতে পারেন যে মানটি ব্যাখ্যা করা হয়নি তবে কেবল হিসাবে ব্যবহৃত হয়েছিল "$1'

এখন আমরা (নিরাপদে) সুডো ব্যবহার করতে পারি:

$ sudo bash -c 'cd -P -- "$1"; pwd' _ "$myvar"
_: line 0: cd: ./path to/my directory";date -u;"true: No such file or directory

যদি বেশ কয়েকটি যুক্তি থাকে তবে আপনি ব্যবহার করতে পারেন:

$ sudo bash -c 'printf "<%s>" "$@"' _ "$val1" "$val2" "$val3"

-2

একক উদ্ধৃতি এখানে কাজ করবে না, তারপরে আপনার ভেরিয়েবল প্রসারিত হবে না। আপনি যদি নিশ্চিত হন যে আপনার পথের পরিবর্তনশীলটি স্যানিটাইজড হয়েছে, তবে সর্বাধিক সহজ সমাধানটি হ'ল ফলস শেলটিতে একবার আসার পরে ফলাফলটির প্রসারকে ঘিরে সহজেই উদ্ধৃতি যুক্ত করা:

sudo bash -c "cd \"$myvar\""

2
এখনও একটি কমান্ড ইনজেকশন দুর্বলতার, এর মানের জন্য পছন্দ $myvarমত $(reboot)বা"; reboot; #
Stéphane Chazelas

1
ব্যবহার sudo bash -c "cd -P -- '$myvar'"শুধুমাত্র মূল্যবোধের সমস্যা সীমাবদ্ধ থাকতে হবে $myvar যে একক উদ্ধৃতি অক্ষর যা নির্বিষ করার সহজ হবে ধারণ করে।
স্টাফেন চেজেলাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.