क्या `xargs sudo rm -rf` को चलाने के लिए फ़ाइल नाम का उपयोग करना पर्याप्त सुरक्षा है?


10

मैंने एक स्क्रिप्ट लिखी थी जो एक फ़ोल्डर में अंतिम दो फ़ाइलों को छोड़कर सभी को हटा देती है:

#!/bin/bash
ls -1 --quoting-style=shell-always /path/to/some/folder \
    | head -n -2 \
    | xargs printf -- "'/path/to/some/folder/%s'\n" \
    | xargs sudo rm -rf

इस स्क्रिप्ट को हर दिन क्रोन जॉब के रूप में निष्पादित किया जाएगा।

तर्क इस प्रकार है:

  1. सभी फ़ाइलों का उपयोग करके एक सूची प्राप्त करें ls -1(ताकि मुझे प्रति पंक्ति एक फ़ाइल मिल सके);

  2. अंतिम दो का उपयोग कर सूची से निकालें head -n -2;

  3. चूंकि lsसापेक्ष पथ प्रिंट करता है, xargs printfफ़ोल्डर पथ को प्रीपेन्ड करने और इसे पूर्ण पथ बनाने के लिए चीज़ का उपयोग करें ;

  4. उन्हें sudo rm -rfउपयोग करने के लिए भेजें xargs

इस फ़ोल्डर में सभी की पहुंच है, इसलिए कोई भी इस फ़ोल्डर में किसी भी फ़ाइल को बना और हटा सकता है।

समस्या यह है: sudo rm -rf डरावना है। xargs sudo rm -rfअविश्वसनीय रूप से डरावना है।

मैं यह सुनिश्चित करना चाहता हूं कि कोई भी अन्य फ़ोल्डर / सिस्टम को नष्ट करने के लिए चतुर फ़ाइलों को बनाने से नुकसान नहीं पहुंचा सकता है (या तो गलती से या उद्देश्य पर)। मुझे नहीं पता, जैसे कुछ चालाक:

file with / spaces.txt

जिसके परिणामस्वरूप एक सुपर डरावना हो सकता है sudo rm -rf /

संपादित करें: मेरी गलती, फ़ाइल नाम शामिल नहीं हो सकते हैं /, इसलिए यह विशिष्ट समस्या नहीं होगी, लेकिन अन्य जोखिम अभी भी हैं या नहीं, इस बारे में सवाल।

यही कारण है कि मैं उपयोग कर रहा हूं --quoting-style=shell-always, यह रिक्त स्थान के साथ फ़ाइलों के साथ किसी भी चाल को रोकना चाहिए। लेकिन अब मैं सोच रहा हूं कि क्या किसी को फ़ाइल नाम में रिक्त स्थान और उद्धरण के साथ अतिरिक्त चतुर हो सकता है ।

क्या मेरी स्क्रिप्ट सुरक्षित है?


नोट: मुझे आवश्यकता है sudoक्योंकि मैं फ़ोल्डर को दूरस्थ रूप से (मैप्ड नेटवर्क ड्राइव का उपयोग करके mount) स्वीकार कर रहा हूं, और मैं इसे sudo के बिना काम करने के लिए नहीं प्राप्त कर सका।


3
क्या आपने ऐसा कुछ करने पर विचार किया है printf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rm?
इस्पात

क्या /नाम में चरित्र के साथ एक फ़ाइल बनाई जा सकती है जिसे मैं यहाँ वापस हासिल करने की कोशिश कर रहा हूँ
जॉर्ज उडोपन

3
@ जॉर्ज नहीं, फ़ाइल नाम में कोई स्लैश नहीं हो सकता।
वेजेंड्रिया

इसलिए जब ओपी कहता है कि चतुर व्यक्ति मैं सोच रहा था ...
जॉर्ज उदेन

6
केवल इसलिए कि आप lsआउटपुट को पार्स कर रहे हैं यह पहले से ही एक खराब लिखित कमांड है, यहां तक ​​कि उद्धरण के साथ भी। lsमैं क्रमबद्ध करने के लिए लोकेल का भी उपयोग करता हूं, मुझे लगता है, इसलिए मैं यह नहीं देखता कि headअंतिम 2 को हटाने का क्या उद्देश्य है (जब तक कि आप छुटकारा पाने की कोशिश नहीं कर रहे हैं .और ..जो कि iirc को rmवैसे भी तर्क के रूप में अनुमति नहीं है। बस उपयोग करें find /path/to/folder -type f delete। ... नहीं, sudoअगर आप क्रोन से चलते हैं - क्रॉन पहले से ही जड़ स्तर पर है
सर्जियो कोलोडियाज़नी

जवाबों:


10

लिनक्स में, कोई भी चरित्र एक मान्य फ़ाइल नाम बनाने वाला चरित्र है:

  • \0 (ASCII NUL): जैसा कि C में स्ट्रिंग समाप्ति के लिए उपयोग किया जाता है
  • / (आगे स्लैश): पथ पृथक्करण के लिए उपयोग किया जाता है

तो, आपका दृष्टिकोण निश्चित रूप से कई मामलों में काम नहीं करेगा जैसा कि आप कल्पना कर सकते हैं जैसे यह \nफ़ाइल नाम में एक नई रेखा ( ) को संभालता है ? ( संकेत: नहीं )।

कुछ नोट:

  • तोता मत करो ls; समर्पित उपकरण का उपयोग करें (अधिकांश उपयोग मामलों के लिए कम से कम एक है)
  • फ़ाइल नाम के साथ काम करते समय, लगभग सभी GNU टूल द्वारा प्रदान किए गए NUL अलग आउटपुट का लाभ उठाने की कोशिश करें जो इस तरह के डेटा के साथ काम करते हैं
  • ध्यान रखें कि पाइपिंग करते समय, सुनिश्चित करें कि दोनों प्रोग्राम एनयूएल अलगाव को समझ सकते हैं
  • जब भी आप आह्वान कर रहे हों xargs, देखें कि क्या आप दूर हो सकते हैं find ... -exec; ज्यादातर मामलों में, आप सिर्फ findअकेले के साथ ठीक हो जाएंगे

मुझे लगता है कि ये आपको अभी के लिए जा रहे हैं। Steeldriver ने पहले ही टिप्पणी में NUL से अलग विचार प्रदान किया है ( printf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rm), इसे एक प्रारंभिक बिंदु के रूप में उपयोग करें।


आपके उत्तर के लिए धन्यवाद :) मुझे लगता है कि आपको केवल उल्लेख करने के बजाय स्टीलड्राइवर की टिप्पणी को उद्धृत करना चाहिए (क्योंकि टिप्पणियां स्थायी नहीं हैं)। मैं findसुझाव के लिए धन्यवाद के रूप में अच्छी तरह से एक नज़र रखना होगा ।
पेड्रो ए

हालांकि मेरा एक सवाल है: मुझे समझ नहीं आ रहा है कि "आपके दृष्टिकोण का क्या अर्थ है निश्चित रूप से कई मामलों में काम नहीं करेगा जैसा कि आप कल्पना कर सकते हैं" - "काम नहीं" जैसे कि "सुरक्षित नहीं" या "असुरक्षित नहीं"? क्योंकि "आपका दृष्टिकोण" मुझे संदर्भित करता है और दुर्भावनापूर्ण उपयोगकर्ता को नहीं, और आपके पूर्व कथन मेरे पक्ष में हैं, इसलिए मैं भ्रमित हूं।
पेड्रो ए

@PedroA आप कर रहे हैं आप के रूप में सभी पात्रों को छोड़कर दो उल्लेख मान्य हैं :) जैसा कि मैंने कहा, आप इनके समेत कई मामलों अपने कल्पना में सक्षम होना चाहिए lsपार्स दृष्टिकोण जैसे विफल हो जाएगा कि आप खाते में फ़ाइल नाम में एक नई पंक्ति ले?
हेम्यल

ओह, फ़ाइल नाम में एक नई ... मैंने ऐसा नहीं सोचा था। यदि आप अपने जवाब में यह भी जोड़ने में कोई आपत्ति नहीं करते हैं :) इसके अलावा, पूछने के लिए क्षमा करें, लेकिन क्या करता head -zहै? यह हास्यास्पद लगता है, लेकिन मेरे पास न manही infoमेरे कोरोस कंटेनर लाइनक्स में है ... इंटरनेट में भी नहीं मिला। मुझे मिलता हैhead: invalid option 'z'
पेड्रो ए

@PedroA न्यूलाइन सिर्फ एक मामला है, ऐसे कई हैं जैसे आपने अनुमान लगाया होगा । आपको जीएनयू head(जीएनयू के साथ आता है coreutils) की आवश्यकता है। यहाँ ऑनलाइन संस्करण है: manpages.ubuntu.com/manpages/xenial/man1/head.1.html
heemayl

3

xargs कुछ उद्धरणों का समर्थन करता है: सिंगल कोट्स, डबल कोट्स या बैकस्लैश के साथ, जो इसे मनमानी तर्क को स्वीकार करने की अनुमति देता है, लेकिन एक सिंटैक्स के साथ जो बॉर्न-जैसे गोले के उद्धरण सिंटैक्स से अलग है।

उबुन्टु lsपर पाए गए GNU कार्यान्वयन में कोई भी उद्धरण मोड नहीं है जो xargsइनपुट प्रारूप के साथ संगत है ।

यह ls --quoting-style=shell-alwaysवाक्य रचना को उद्धृत करते हुए ksh93, bash और zsh के गोले के साथ संगत है, लेकिन केवल जब lsशेल द्वारा व्याख्या की गई आउटपुट को उसी लोकेल में समझा जाता है lsजब यह आउटपुट था। इसके अलावा, कुछ स्थानों, जैसे कि BIG5, BIG5-HKSCS, GBK या GB18030 का उपयोग करने वालों से बचना चाहिए।

तो उन गोले के साथ, आप वास्तव में कर सकते हैं:

typeset -a files
eval "files=($(ls --quoting-style=shell-always))"
xargs -r0a <(printf '%s\0' "${files[@]:0:3}") ...

लेकिन उस पर थोड़ा फायदा है:

files=(*(N))                 # zsh
files=(~(N)*)                # ksh93
shopt -s nullglob; files=(*) # bash

एकमात्र मामला जहां यह उपयोगी हो जाता है, जब आप फ़ाइलों को सॉर्ट करने के -tविकल्प का उपयोग करना चाहते हैं lsmime / atime / ctime या -S/ -V। लेकिन फिर भी, आप उपयोग कर सकते हैं zsh:

files=(*(Nom))

उदाहरण के लिए माइम द्वारा फ़ाइलों को सॉर्ट करना (उपयोग के oLलिए -S, और के nलिए -V)।

सभी को हटाने के लिए लेकिन दो सबसे हाल ही में संशोधित नियमित फ़ाइलें:

rm -f -- *(D.om[3,-1])

execve()Non अभी भी कुछ लंबाई सीमाएँ हैं ( और कुछ गैर-जीएनयू xargsकार्यान्वयन में बहुत कम मनमानी हैं), और कुछ गैर-जीएनयू xargsकार्यान्वयन इनपुट का झंकार करेंगे जिसमें बाइट्स के अनुक्रम होते हैं जो वैध वर्ण नहीं बनाते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.