2009-06-14 9 views
8

अधिकांश लिपियों कि पार्स/proc/cmdline इसे तोड़ने के शब्दों में और उसके बाद, उदाहरण के एक मामले बयान के साथ बहस को फ़िल्टर:विभाजन/proc/cmdline तर्क

CMDLINE="quiet union=aufs wlan=FOO" 
for x in $CMDLINE 
do 
»···case $x in 
»···»···wlan=*) 
»···»···echo "${x//wlan=}" 
»···»···;; 
»···esac 
done 

समस्या है जब WLAN ESSID रिक्त स्थान है। उपयोगकर्ता wlan='FOO बार '(एक शैल चर की तरह) सेट करने की उम्मीद करते हैं और फिर उपरोक्त कोड के साथ 'FOO का अप्रत्याशित परिणाम प्राप्त करते हैं, क्योंकि लूप के लिए रिक्त स्थान पर विभाजन होता है।

क्या /proc/cmdline को एक शेल स्क्रिप्ट से लगभग इसे कम करने से कम करने का कोई बेहतर तरीका है?

या क्या कुछ उद्धरण चाल है? मैं सोच रहा था कि मैं शायद उपयोगकर्ताओं को इकाई उद्धरण रिक्त स्थान और डीकोड करने के लिए कह सकता हूं: /bin/busybox httpd -d "FOO%20BAR"। या यह एक बुरा समाधान है?

+0

आपका खोल पहले ही कमांड लाइन को विभाजित कर रहा है, विभाजन को विभाजित कर रहा है। आप इसे "अयोग्य" क्यों करना चाहते हैं और न केवल यह मान लें कि उपयोगकर्ता तर्क को सही तरीके से उद्धृत करेगा - जैसे कि इसे किसी अन्य आदेश के साथ करना है? यदि आप अंतरिक्ष के साथ एक फ़ाइल को हटाना चाहते हैं, तो आप अंतरिक्ष के साथ «आरएम" फ़ाइल टाइप करें "»। क्या होगा यदि आपका ईएसएसआईडी «essid wlan = FOO» है? – liori

+0

ठीक है, मैंने जेस्पर के रूप में भी यही गलती की है ... – liori

उत्तर

-4

कमांड लाइन तक पहुंचने के लिए शेल-स्क्रिप्ट से/proc/cmdline का उपयोग गलत तरीका है। $ @ का उपयोग क्यों नहीं करें?

for arg in "[email protected]"; do 
    ... 
done 

संपादित करें: $ @ के आसपास उद्धरण उद्धरण।

संपादित करें: प्रश्न को गलत तरीके से पढ़ें;/proc/cmdline कर्नेल कमांड लाइन है।

+0

/proc/cmdline यह है कि लिनक्स डिस्ट्रोज़ पर तर्क कैसे सेट किए जाते हैं। जैसे http://webconverger.org/boot/ – hendry

+0

रिमबर $ @ के आसपास उद्धरणों का उपयोग करने के लिए या इसे फॉर-लूप में विभाजित किया जाएगा। "$ @" में तर्क के लिए उपयोग करें; करें ... –

+0

@hendry: क्षमा करें, मैं इसे "/ proc/pID/cmdline" के रूप में गलत तरीके से पढ़ता हूं।/proc/cmdline चल रहे कर्नेल की कमांड लाइन है, और/proc/pID/cmdline प्रक्रिया पीआईडी ​​की कमांड लाइन है। मुझे अभी भी समझ में नहीं आता कि आप कर्नेल कमांड लाइन का विश्लेषण क्यों करना चाहते हैं। मुझे कर्नेल हैकिंग के बारे में बहुत कुछ पता नहीं है, लेकिन यह चल रहा कर्नेल के बारे में जानकारी जानने के लिए पार्सिंग/proc/cmdline की तरह लगता है गलत दृष्टिकोण है। – JesperE

0

आलीशान में:

$ f() { echo $1 - $3 - $2 - $4 
> } 
$ a="quiet union=aufs wlan=FOO" 
$ f $a 
quiet - wlan=FOO - union=aufs - 

आप एक समारोह को परिभाषित करने और दे सकते हैं अपने $ cmdline गैर उद्धृत कार्य करने के लिए एक तर्क के रूप। फिर आप शैल की पार्सिंग तंत्र का आह्वान करेंगे। ध्यान दें, आपको उस शेल पर इसका परीक्षण करना चाहिए जिसमें यह काम करेगा - zsh कुछ मज़ेदार चीजें उद्धरण के साथ करता है ;-)।

तो फिर तुम सिर्फ खोल में की तरह के हवाले करने के लिए उपयोगकर्ता बता सकते हैं:

#!/bin/posh 
CMDLINE="quiet union=aufs wlan=FOO" 
f() { 
     while test x"$1" != x 
     do  
       case $1 in 
         union=*)  echo ${1##union=}; shift;; 
         *)    shift;; 
       esac  
     done  
}  
f $CMDLINE 

(आलीशान - नीति-संगत साधारण खोल, एक खोल मानक POSIX से परे किसी भी सुविधाओं से वंचित)

+0

क्योंकि आप अधिक तर्क ($ 2, $ 3 ... और अधिक बदलावों के साथ) खा सकते हैं। मैं सहमत हूं कि यह x = y तर्कों के लिए इतना उपयोगी नहीं है; -x वाई के लिए और अधिक। लेकिन यह समाधान अधिक बहुमुखी और थोड़ा अधिक मूर्खतापूर्ण है (इसे अक्सर खोल स्क्रिप्ट में देखकर)। – liori

+0

तो उपयोगकर्ता 'फू बार' जैसे एसिड को कैसे उद्धृत करेंगे? wlan = foo \ 040bar अन्य उत्तर की तरह? मैं ईमानदारी से सोचता हूं कि यूआरएल एन्कोडिंग "% 20" शेल ऑक्टल एन्कोडिंग की तुलना में औसत उपयोगकर्ता के लिए आसान है। – hendry

+1

इस मामले में, एक शेल-जैसी एस्केपिंग लागू होगी: सीएमडीलाइन = "शांत wlan = 'foo bar bar union = of = उपभोक्ता और अभी तक एक और शब्द' संघ = aufs"। लेकिन ... अब मुझे लगता है कि अगर इसका मतलब कर्नेल पैरामीटर भी है, तो आपको ऑक्टल का उपयोग करना चाहिए। कर्नेल खोल विस्तार नहीं करता है और ऊपर wlan आईडी देखकर उलझन में हो सकता है। – liori

3

सबसे अधिक , \0ctal एस्केप अनुक्रमों का उपयोग तब किया जाता है जब रिक्त स्थान अस्वीकार्य होते हैं।

बैश में, printf का उपयोग उन्हें अनदेखा करने के लिए किया जा सकता है, उदा।

CMDLINE='quiet union=aufs wlan=FOO\040BAR' 
for x in $CMDLINE; do 
    [[ $x = wlan=* ]] || continue 
    printf '%b\n' "${x#wlan=}" 
done 
+0

मैं वेब स्टाइल इकाई उद्धरण पसंद करता हूं। – hendry

+0

यूनिक्स से बचने के लिए अस्थायी भाग्य अधिक आम (और पारंपरिक) हैं। उदाहरण के लिए,/etc/fstab में पथ माउंट करने के लिए रिक्त स्थान जोड़ने का तरीका है। – ephemient

+0

चूंकि यह "वेब उत्पाद" वेबकॉन्वरर के लिए पैरामीटर है, जहां होमपेज जैसे अन्य पैरामीटर http://webconverger.org/boot/ भी URL एन्कोड किए जाएंगे, मुझे लगता है कि मेरी प्रारंभिक पसंद सर्वोत्तम है। – hendry

10

वहाँ कुछ तरीके हैं:

  1. cat /proc/PID/cmdline | tr '\000' ' '

  2. cat /proc/PID/cmdline | xargs -0 echo

ये ज्यादातर मामलों के साथ काम करेंगे, लेकिन असफल हो जायेगी जब तर्क उन में रिक्त स्थान है। हालांकि मुझे लगता है कि /proc/PID/cmdline का उपयोग करने से बेहतर दृष्टिकोण होंगे।

+4

'/ proc/cmdline''/proc/pID/cmdline' से काफी अलग है ... –

+0

कुछ बूटलोडर (ग्रब, लीलो, SysLinux द्वारा कर्नेल को प्रदान की गई कमांड लाइन '/ proc/cmdline' अधिक विशिष्ट होने के लिए , आदि)। '/ proc/$ पीआईडी ​​/ cmdline' कमांड लाइन है जिसे प्रत्येक प्रक्रिया के लिए 'execve()' सिस्टम कॉल द्वारा संसाधित किया जाता है। –

+0

जो सबसे ऊपर की ओर से बेहतर समाधान है: लघु और बिंदु (मानक उपकरण का उपयोग करके रिक्त स्थान के साथ '\ 000' को प्रतिस्थापित करें) – akappa

1

आप निम्न का उपयोग कर बैश, जो $ cmdline_union की तरह चर करने के लिए उन तर्कों चालू करेंगे और $ cmdline_wlan की तरह कुछ कर सकता है:

bash -c "for i in $(cat /proc/cmdline); do printf \"cmdline_%q\n\" \"\$i\"; done" | grep = > /tmp/cmdline.sh 
. /tmp/cmdline.sh 

तो फिर तुम बोली और/या आप जैसे में होगा चीजों से बचने के हैं एक सामान्य खोल

8
set -- $(cat /proc/cmdline) 
for x in "[email protected]"; do 
    case "$x" in 
     wlan=*) 
     echo "${x#wlan=}" 
     ;; 
    esac 
done 
+0

बहुत ही सुरुचिपूर्ण समाधान! एक्स के लिए –

+0

'; do' ... एक ही अर्थशास्त्र के लिए 'x में "$ @" के रूप में डिफ़ॉल्ट; करें ... ' लेकिन अधिक स्पष्ट रूप है ... और अधिक स्पष्ट। बस एक साइड नोट। :) –

-1

मिले here एक अच्छा तरीका awk साथ यह करने के लिए, दुर्भाग्य से यह doublequotes के साथ ही काम करेगा:

# Replace spaces outside double quotes with newlines 
args=`cat /proc/cmdline | tr -d '\n' | awk 'BEGIN {RS="\"";ORS="\"" }{if (NR%2==1){gsub(/ /,"\n",$0);print $0} else {print $0}}'` 

IFS='                   
'                    
for line in $args; do               
    key=${line%%=*}                
    value=${line#*=}               

    value=`echo $value | sed -e 's/^"//' -e 's/"$//'`       

    printf "%20s = %s\n" "$key" "$value"          

done 
1

आप खोल पार्स करने के लिए चाहते हैं के बाद से/proc/cmdline सामग्री है, यह मुश्किल है इसे eval'ing से बचें।

#!/bin/bash 
eval "kernel_args=($(cat /proc/cmdline))" 
for arg in "${kernel_args[@]}" ; do 
    case "${arg}" in 
     wlan=*) 
      echo "${arg#wlan=}" 
      ;; 
    esac 
done 

यह आँख बंद करके कुछ भी है कि quiet union=aufs wlan=FOO) ; touch EVIL ; q=(q की तरह गिरी कमांड लाइन पर निर्दिष्ट किया गया था चल पाएंगे जैसे कि स्पष्ट रूप से खतरनाक है।

रिक्त स्थान से बचने (\ x20) सबसे सरल और सुरक्षित तरीके की तरह लगता है।

कुछ पार्सर का उपयोग करने के लिए एक भारी विकल्प है, जो शैल-जैसी वाक्यविन्यास को समझता है। इस मामले में, आपको अब भी शैल की आवश्यकता नहीं हो सकती है। उदाहरण के लिए, पायथन के साथ:

$ cat /proc/cmdline 
quiet union=aufs wlan='FOO BAR' key="val with space") ; touch EVIL ; q=(q 
$ python -c 'import shlex; print shlex.split(None)' < /proc/cmdline 
['quiet', 'union=aufs', 'wlan=FOO BAR', 'key=val with space', ')', ';', 'touch', 'EVIL', ';', 'q=(', 'q'] 
संबंधित मुद्दे