এটি $ BASH_COMMAND খালি নিরাপদ?


11

আমি একটি শেল স্ক্রিপ্টে কাজ করছি যা ভেরিয়েবলগুলি থেকে একটি জটিল কমান্ড তৈরি করে, উদাহরণস্বরূপ (এমন একটি কৌশল সহ যা আমি বাশ FAQ থেকে শিখেছি ):

#!/bin/bash

SOME_ARG="abc"
ANOTHER_ARG="def"

some_complex_command \
  ${SOME_ARG:+--do-something "$SOME_ARG"} \
  ${ANOTHER_ARG:+--with "$ANOTHER_ARG"}

এই স্ক্রিপ্টটি পরিবর্তনশীল পরামিতি যোগ করা --do-something "$SOME_ARG"এবং --with "$ANOTHER_ARG"করতে some_complex_commandযদি এই ভেরিয়েবল সংজ্ঞায়িত করা হয়। এখন পর্যন্ত এটি ঠিকঠাক কাজ করছে।

তবে এখন আমি কমান্ডটি চালানোর সময় মুদ্রণ বা লগ করতে সক্ষম হতে চাই, উদাহরণস্বরূপ যখন আমার স্ক্রিপ্টটি ডিবাগ মোডে চালিত হয়। সুতরাং যখন আমার স্ক্রিপ্টটি চলবে some_complex_command --do-something abc --with def, আমি এই কমান্ডটি একটি ভেরিয়েবলের ভিতরে রাখতে চাই যাতে আমি উদাহরণস্বরূপ এটি সিসলগে লগইন করতে পারি।

বাশ এফএকিউ এই উদ্দেশ্যে ফাঁদ এবং পরিবর্তনশীল (উদাহরণস্বরূপ ডিবাগিং উদ্দেশ্যে) ব্যবহার করারDEBUG$BASH_COMMAND জন্য একটি কৌশল প্রদর্শন করে । আমি নিম্নলিখিত কোড সহ চেষ্টা করেছি:

#!/bin/bash

ARG="test string"

trap 'COMMAND="$BASH_COMMAND"; trap - DEBUG' DEBUG
echo "$ARG"

echo "Command was: ${COMMAND}"

এটি কাজ করে, তবে কমান্ডের মধ্যে ভেরিয়েবলগুলি প্রসারিত করে না:

host ~ # ./test.sh
test string
Command was: echo "$ARG"

আমার ধারণা আমি প্রসারিত echo "$ARG"করতে ইওল ব্যবহার করতে হবে echo test string(কমপক্ষে আমি evalএখনও ছাড়া উপায় খুঁজে পাইনি )। নিম্নলিখিত কাজ করে:

eval echo "Command was: ${COMMAND}"

এটি নিম্নলিখিত আউটপুট উত্পাদন করে:

host ~ # ./test.sh
test string
Command was: echo "$ARG"
Command was: echo test string

তবে আমি যদি evalনিরাপদে এভাবে ব্যবহার করতে পারি তবে আমি সত্যই নিশ্চিত নই । আমি কিছু জিনিস শোষণ করার ব্যর্থ চেষ্টা করেছি:

#!/bin/bash

ARG="test string; touch /x"
DANGER='$(touch /y; cat /etc/shadow)'

trap 'COMMAND="$BASH_COMMAND"; trap - DEBUG' DEBUG
echo "$ARG" $DANGER

echo "Command was: ${COMMAND}"
eval echo "Command was: ${COMMAND}"

এটি এটিকে ভালভাবে পরিচালনা করছে বলে মনে হয় তবে আমি আগ্রহী যদি অন্য কোনও সমস্যা মিস করে যা আমি দেখি।


এটি আমি বছরের পর বছর ধরে একটি সুডো মোড়কে ব্যবহার করে আসছি, আমি কখনই কোনও সমস্যা লক্ষ্য করিনি।
w00t

উত্তর:


7

একটি সম্ভাবনা হ'ল একটি মোড়ক ফাংশন করা যা একই সাথে কমান্ডটি মুদ্রণ করবে এবং এটি সম্পাদন করবে:

debug() {
    # This function prints (to stdout) its arguments and executes them
    local args=() idx=0 IFS=' ' c
    for c; do printf -v args[idx++] '%q' "$c"; done
    printf "%s\n" "${args[*]}"
    # Execute!
    "$@"
}

যাতে আপনার স্ক্রিপ্টে আপনি এটি করতে পারেন:

debug echo "$ARG"

ফাঁদ দিয়ে গলগল করার দরকার নেই। ত্রুটিটি হ'ল এটি আপনার কোডগুলিতে কিছু debugকীওয়ার্ড যুক্ত করে (তবে এটি ভাল হওয়া উচিত, এ জাতীয় স্টাফগুলির যেমন জোর দেওয়া ইত্যাদি) সাধারণ।

আপনি এমনকি একটি গ্লোবাল ভেরিয়েবল যুক্ত করতে পারেন DEBUGএবং এর debugমতো ফাংশনটি সংশোধন করতে পারেন:

debug() {
    # This function prints (to stdout) its arguments if DEBUG is non-null
    # and executes them
    if [[ $DEBUG ]]; then
        local args=() idx=0 IFS=' ' c
        for c; do printf -v args[idx++] '%q' "$c"; done
        printf "%s\n" "${args[*]}"
    fi
    # Execute!
    "$@"
}

তারপরে আপনি আপনার স্ক্রিপ্টটিকে এভাবে কল করতে পারেন:

$ DEBUG=yes ./myscript

অথবা

$ DEBUG= ./myscript

বা শুধু

$ ./myscript

আপনি ডিবাগ তথ্য পেতে চান কিনা তা নির্ভর করে।

আমি DEBUGপরিবর্তনশীলটিকে মূলধন করেছিলাম কারণ এটি পরিবেশের পরিবর্তনশীল হিসাবে বিবেচনা করা উচিত। DEBUGএটি একটি তুচ্ছ এবং সাধারণ নাম, তাই এটি অন্যান্য কমান্ডের সাথে সংঘর্ষে লিপ্ত হতে পারে। হয়তো এটা কল GNIOURF_DEBUGবা MARTIN_VON_WITTICH_DEBUGবা UNICORN_DEBUGআপনি ইউনিকর্ন মত (এবং তারপর আপনি সম্ভবত ponies মতো সহজেই)।

বিঃদ্রঃ. ইন debugফাংশন, আমি সাবধানে সঙ্গে প্রতিটি যুক্তি ফরম্যাট printf '%q'যাতে আউটপুট সঠিকভাবে পলান করা হবে এবং তাই উদ্ধৃত যেমন সরাসরি কপি সঙ্গে পুনর্ব্যবহারযোগ্য ধারণকৃত হতে হবে এবং পেস্ট করতে। এটি শেলটি ঠিক কী দেখেছে তাও আপনাকে প্রদর্শন করবে যেহেতু আপনি প্রতিটি যুক্তি খুঁজে বের করতে সক্ষম হবেন (ফাঁকা জায়গা বা অন্যান্য মজার চিহ্নগুলির ক্ষেত্রে)। এই ফাংশনটি অগত্যা সাবশেলগুলি এড়াতে যাতে -vস্যুইচের সাথে সরাসরি অ্যাসাইনমেন্টও ব্যবহার করে printf


1
ফাংশন দুর্দান্ত কাজ করে তবে দুর্ভাগ্যক্রমে আমার কমান্ডে পুনর্নির্দেশগুলি এবং "ব্যাকগ্রাউন্ডে এক্সাইটেট" কন্ট্রোল অপারেটর রয়েছে &। এটিকে কাজ করার জন্য আমাকে তাদের ফাংশনে স্থানান্তরিত করতে হয়েছিল - খুব সুন্দর নয়, তবে আমি এর চেয়ে ভাল উপায় বলে মনে করি না। কিন্তু আর eval, তাই আমি পেয়েছেন আমার জন্য যাচ্ছে, যা সুন্দর :)
মার্টিন ভন Wittich

5

eval "$BASH_COMMAND" কমান্ড চালায়।

printf '%s\n' "$BASH_COMMAND" সঠিক নির্দিষ্ট কমান্ড, এবং একটি নতুন লাইন প্রিন্ট করে।

যদি কমান্ডটিতে ভেরিয়েবল থাকে (যেমন এটির মতো কিছু থাকে cat "$foo") তবে কমান্ডটি প্রিন্ট করে ভেরিয়েবলের পাঠ্য প্রিন্ট করা যায়। কমান্ডটি কার্যকর না করে ভেরিয়েবলের মান মুদ্রণ করা অসম্ভব - কমান্ডের মতো চিন্তা করুন variable=$(some_function) other_variable=$variable

শেল স্ক্রিপ্টটি সম্পাদন করা থেকে সন্ধানের সহজ উপায় হ'ল স্ক্রিপ্টটি xtraceচালিয়ে bash -x /path/to/scriptবা set -xশেলের অভ্যন্তরে প্রবেশ করে শেল বিকল্পটি সেট করা । ট্রেসটি স্ট্যান্ডার্ড ত্রুটিতে মুদ্রিত হয়।


1
আমি জানি xtrace, কিন্তু এটি আমাকে খুব বেশি নিয়ন্ত্রণ দেয় না। আমি "সেট-এক্স; ...; সেট + এক্স" চেষ্টা করেছি, কিন্তু: ১) xtrace অক্ষম করার জন্য "সেট + এক্স" কমান্ডটি খুব বেশি মুদ্রিত হয়েছে) আউটপুট যেমন আমি টাইমস্ট্যাম্প সহ উপস্থাপন করতে পারি না 3) আমি পারি সিসলগে এটি লগ করা যাবে না।
মার্টিন ভন উইট্টিচ

2
"কমান্ড কার্যকর না করে ভেরিয়েবলের মান মুদ্রণ করা অসম্ভব" - ভাল উদাহরণ, আমি এরকম কেসটি বিবেচনা করি নি। এটি খুব ভাল লাগবে যদিও বাশের BASH_COMMANDবর্ধিত কমান্ডের পাশে একটি অতিরিক্ত পরিবর্তনশীল থাকে, কারণ এটি কার্যকর করার সময় কোনও কোনও সময়ে এটি কমান্ডটিতে পরিবর্তনশীল সম্প্রসারণ করতে হবে :)
মার্টিন ভন উইটিক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.