जवाबों:
sudo su -, जो लेखन का एक जटिल तरीका है sudo -i, एक प्राचीन वातावरण का निर्माण करता है। यह एक लॉगिन शेल का बिंदु है। यहां तक कि एक सादा sudoवातावरण से अधिकांश चर हटाता है। इसके अलावा sudoएक बाहरी आदेश है; शेल स्क्रिप्ट में विशेषाधिकारों को बढ़ाने का कोई तरीका नहीं है, केवल एक बाहरी प्रोग्राम ( sudo) को अतिरिक्त विशेषाधिकारों के साथ चलाने के लिए , और इसका अर्थ है कि शेल शेल (यानी गैर-निर्यात किए गए चर) और पैरेंट शेल में परिभाषित फ़ंक्शन उपलब्ध नहीं होंगे। बच्चे के खोल।
आप एक लॉगिन शेल ( या के sudo bashबजाय ) को इनवॉइस करके और इन वेरिएबल्स को ( फ़ाइल में या उसके माध्यम से) जाने के लिए इनवायरमेंट वेरिएबल्स को पास कर सकते हैं । यह आपको फ़ंक्शंस के लिए मदद नहीं करेगा (हालाँकि बैश में फंक्शन एक्सपोर्ट की सुविधा है, sudo इसे ब्लॉक करता है)।sudo su -sudo -iDefaults !env_resetDefaults env_keep=…sudoers
बच्चे के खोल में अपने कार्यों को प्राप्त करने का सामान्य तरीका उन्हें वहां परिभाषित करना होगा। उद्धृत करने का ध्यान रखें: यदि आप <<EOFयहाँ दस्तावेज़ के लिए उपयोग करते हैं , तो यहाँ दस्तावेज़ की सामग्री को पहले मूल शेल द्वारा विस्तारित किया गया है, और उस विस्तार का परिणाम उस स्क्रिप्ट का हो जाता है जिसे बच्चा शेल देखता है। यानि अगर आप लिखते हैं
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
यह मूल उपयोगकर्ता का नाम प्रदर्शित करता है, लक्ष्य उपयोगकर्ता का नहीं। विस्तार के इस पहले चरण से बचने के लिए, <<ऑपरेटर के बाद यहाँ दस्तावेज़ मार्कर को उद्धृत करें :
sudo -u "$target_user" -i <<'EOF'
echo "$(whoami)"
EOF
इसलिए यदि आपको माता-पिता के खोल से बच्चे के खोल तक डेटा पास करने की आवश्यकता नहीं है, तो आप यहाँ एक दस्तावेज का उपयोग कर सकते हैं:
#!/bin/bash
sudo -u "$target_user" -i <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}"
EOF
यद्यपि आप पेरेंट शेल से चाइल्ड शेल में डेटा को पास करने के लिए एक अनकॉन्डेट यहाँ डॉक्यूमेंट मार्कर का उपयोग कर सकते हैं, यह केवल तभी काम करता है जब डेटा में कोई विशेष वर्ण न हो। ऐसा इसलिए है क्योंकि एक स्क्रिप्ट में
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
आउटपुट whoamiएक शेल कोड का एक सा हो जाता है, न कि एक स्ट्रिंग। उदाहरण के लिए, यदि whoamiकमांड वापस आती है "; rm -rf /; "trueतो चाइल्ड शेल कमांड को निष्पादित करेगा echo ""; rm -rf /; "true"।
यदि आपको मूल शेल से डेटा पास करने की आवश्यकता है, तो एक सरल तरीका यह है कि इसे तर्क के रूप में पारित किया जाए। बच्चे के खोल को स्पष्ट रूप से आह्वान करें और इसे स्थितिगत मापदंडों को पास करें:
#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i sh _ "$extVAR" <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}" "${1}"
EOF
यदि आपके पास पास करने के लिए कई चर हैं, तो उन्हें नाम से पास करना अधिक पठनीय होगा। envबच्चे के खोल के लिए पर्यावरण चर सेट करने के लिए स्पष्ट रूप से कॉल करें ।
#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i env extVAR="$extVAR" sh <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}" "${1}"
EOF
ध्यान दें कि यदि आप अपेक्षित हैं /etc/profileऔर लक्षित उपयोगकर्ता ~/.profileको पढ़ा जाना है, तो आपको उन्हें स्पष्ट रूप से पढ़ना होगा, या bash --loginइसके बजाय कॉल करना होगा sh।
यह कार्य नहीं करता है क्योंकि फ़ंक्शन आपके द्वारा लॉन्च किए log_fगए sudo su -शेल में घोषित नहीं है । बजाय:
extVAR="yourName"
sudo su - <user> << EOF
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f ${intVAR} ${extVAR}
EOF
आपको फ़ंक्शन को रूट उपधारा में परिभाषित करने की आवश्यकता है। वह यह कर सकता है, लेकिन .... मुझे नहीं पता कि उस सामान में से अधिकांश क्या करता है। कम से कम - तो जब तक और न sudoही suपासवर्ड पढ़ने के लिए स्टड की जरूरत है - तब तक log_f()घोषित किया जाना चाहिए ।
मुझे विश्वास है कि आप उन मूल्यों को रूट शेल के इनपुट में विस्तारित करने का मतलब है, वैसे। यदि आपको ऐसा करने का मतलब नहीं है, तो आपको EOFखुद को कोट करना चाहिए ।
मेरे मामले में मैं में एक सरणी पारित करने के लिए की जरूरत है और कुछ परेशानी थी, लेकिन, जबकि एक के लिए सरणी के मूल्यों गूंज से एक के बाद सफलता मिली env-कुंजी और में इरादा कोड लपेटकर bash -c '<intended code>', और मूल रूप से है यह सरणी जैसे पुनः, .: INNER_KEY=($<env_key>)।
परीक्षा के लिए:
#!/usr/bin/env bash
PLUGINS=(foo bar baz)
sudo -u <some-user> -i env PLUGINS="`echo ${PLUGINS[@]}`" sh <<'EOF'
bash -c '
FOO=($PLUGINS);
echo values: \[${FOO[@]}\];
for pl in ${FOO[@]};
do echo value: $pl;
done;
'
EOF
समस्या यह थी कि मैं सीधे निम्नलिखित की तरह कुछ नहीं कर सकता था (उपयोग नहीं bash -c '...'):
FOO=($PLUGINS);
for pl in ${FOO[@]};
...