अपरिवर्तनीय विशेषता सेट वाली फ़ाइलों की खोज कैसे करें?


18

कॉन्फ़िगरेशन ऑडिटिंग कारणों के लिए, मैं उन फ़ाइलों के लिए अपने ext3 फाइल सिस्टम को खोजने में सक्षम होना चाहता हूं जिनके पास अपरिवर्तनीय विशेषता सेट (के माध्यम से chattr +i) है। मुझे ऐसा करने के लिए findया इसके समान कोई विकल्प नहीं मिल रहा है । इस बिंदु पर, मुझे डर है कि मुझे lsattrप्रत्येक निर्देशिका के लिए आउटपुट को पार्स करने के लिए अपनी स्क्रिप्ट लिखनी होगी । क्या एक मानक उपयोगिता है जो एक बेहतर तरीका प्रदान करती है?


मुझे यह स्पष्ट करना चाहिए कि मेरे मामले में, मैं बस कॉन्फ़िगर प्रबंधन के लिए ऑडिट कर रहा हूं, घुसपैठ का पता नहीं लगा रहा हूं, इसलिए मुझे नई कहानियों के बारे में बहुत अधिक चिंता करने की आवश्यकता नहीं है, क्योंकि मुझे पता है कि मैं जिन फ़ाइल नामों के साथ काम कर रहा हूं, उनके बारे में पता नहीं होगा। उन्हें। फिर भी, न्यूलाइन मुद्दा ध्यान में रखने योग्य है, इसलिए मैं अपने प्रश्न को इस तरह छोड़ दूंगा।
depquid

जवाबों:


9

यह grepकमांड को lsattrकमांड करने के लिए पाइपिंग द्वारा आंशिक रूप से पूरा किया जा सकता है ।

lsattr -R | grep +i

हालाँकि, मेरा मानना ​​है कि जब आप संपूर्ण ext3फ़ाइल सिस्टम का उल्लेख करते हैं तो खोज में शामिल हो सकते हैं /proc, /devऔर कुछ अन्य निर्देशिकाएं जो यदि कुछ त्रुटि की रिपोर्ट करती हैं तो आप अनदेखा करना चाहते हैं। आप संभवतः कमांड को चला सकते हैं,

lsattr -R 2>/dev/null | grep -- "-i-"

आप स्पष्ट रूप से "-i" से अधिक मिलान करने के लिए पीसीआरई सुविधा grepका उपयोग करके थोड़ा अधिक सख्त बनाना चाह सकते हैं grep

lsattr -R 2>/dev/null | grep -P "(?<=-)i(?=-)"

यह तो इस तरह की स्थितियों के लिए काम करेंगे:

$ lsattr -R 2>/dev/null afile | grep -P "(?<=-)i(?=-)"
----i--------e-- afile

लेकिन अपूर्ण है। यदि अपरिवर्तनीय ध्वज के चारों ओर अतिरिक्त विशेषताएँ सक्षम हैं, तो हम उनका मिलान नहीं करेंगे, और यह उन फ़ाइलों द्वारा मूर्ख बनाया जाएगा जिनके नाम उपरोक्त पैटर्न से मेल खाने के लिए होते हैं, जैसे:

$ lsattr -R 2>/dev/null afile* | grep -P "(?<=-)i(?=-)"
----i--------e-- afile
-------------e-- afile-i-am

हम पैटर्न को इस तरह थोड़ा और कस सकते हैं:

$ lsattr -a -R 2>/dev/null afile* | grep -P "(?<=-)i(?=-).* "
----i--------e-- afile

लेकिन यह अभी भी थोड़ा नाजुक है और आपके फाइल सिस्टम के आधार पर अतिरिक्त ट्विकिंग की आवश्यकता होगी। @StephaneChazeles के रूप में उल्लेख नहीं करने के लिए टिप्पणियों में उल्लेख किया गया है कि उपरोक्त पैटर्न को दरकिनार करने के लिए एक फाइल नाम के साथ newlines के शामिल किए जाने से इसे आसानी से प्राप्त किया जा सकता है grep

संदर्भ

https://groups.google.com/forum/#!topic/alt.os.linux/LkatROg2SlM


1
हा मैंने वही धागा पढ़ा और पोस्ट करने वाला था। मैं आपके बदले अपने एक्स्ट्रा जोड़ दूंगा।
स्लम sl

@ एसएलएम, किसी भी बदलाव के लिए आपका स्वागत है :)
रमेश

2
संभवतः ऑडिटिंग के लिए अच्छा नहीं है क्योंकि उस दृष्टिकोण के साथ फ़ाइल नाम में newline वर्णों के द्वारा नकली या किसी अपरिवर्तनीय फ़ाइल को छिपाया जा सकता है। इसके अलावा, -i-इसके नाम में फ़ाइलनाम होना कोई असामान्य बात नहीं है (वर्तमान में लॉग ऑन किए गए सिस्टम पर 34 हैं)। आप शायद -aविकल्प भी
चाहेंगे

1
जिज्ञासा से बाहर, +iपहले उदाहरण में क्या होना चाहिए? यह मेरे लिए काम नहीं करता है। इसके अलावा, -i-यह मानते हुए कि गुणों के समीप आने i(जैसे a) परेशान हैं।
depquid

1
क्यों नहीं बस के लिए grep ^....i? या कम से कम कुछ ऐसा हो जैसे ^[^ ]*iकि iपांचवी के अलावा दूसरी स्थिति में हो सकता है।
रुस्लान

6

यह देखते हुए कि स्क्रिप्ट का उद्देश्य ऑडिटिंग है, यह विशेष रूप से महत्वपूर्ण है कि मनमाने ढंग से फ़ाइल नामों के साथ सही ढंग से निपटें, उदाहरण के लिए नए नामों वाले नाम। यह lsattrएक साथ कई फ़ाइलों पर उपयोग करना असंभव बनाता है , क्योंकि lsattrउस मामले में आउटपुट अस्पष्ट हो सकता है।

आप एक बार में एक फ़ाइल पर findकॉल कर सकते हैं lsattr। यह हालांकि बहुत धीमी हो जाएगी।

find / -xdev -exec sh -c '
  for i do
     attrs=$(lsattr -d "$i"); attrs=${attrs%% *}
     case $attrs in
       *i*) printf "%s\0" "$i";;
     esac
  done' sh {} +

मैं पर्ल, पाइथन या रूबी जैसी कम क्रैंक भाषा का उपयोग करने और lsattrखुद से काम करने की सलाह देता हूं ।lsattrएक FS_IOC_GETFLAGSioctl syscall जारी करके और फ़ाइल के इनकोड झंडे को पुनः प्राप्त करके संचालित होता है । यहां पाइथन प्रूफ-ऑफ-कॉन्सेप्ट है।

#!/usr/bin/env python2
import array, fcntl, os, sys
S_IFMT =  0o170000
S_IFDIR = 0o040000
S_IFREG = 0o100000
FS_IOC_GETFLAGS = 0x80086601
EXT3_IMMUTABLE_FL = 0x00000010
count = 0
def check(filename):
    mode = os.lstat(filename).st_mode
    if mode & S_IFMT not in [S_IFREG, S_IFDIR]:
        return
    fd = os.open(filename, os.O_RDONLY)
    a = array.array('L', [0])
    fcntl.ioctl(fd, FS_IOC_GETFLAGS, a, True)
    if a[0] & EXT3_IMMUTABLE_FL: 
        sys.stdout.write(filename + '\0')
        global count
        count += 1
    os.close(fd)
for x in sys.argv[1:]:
    for (dirpath, dirnames, filenames) in os.walk(x):
        for name in dirnames + filenames:
            check(os.path.join(dirpath, name))
if count != 0: exit(1)

1
FYI करें पर अपने सिस्टम FS_IOC_GETFLAGSहै 0x80046601
एंटोनोन

1
के मूल्य पर FS_IOC_GETFLAGSनिर्भर करता है sizeof(long)। उदाहरण के लिए, C में मैक्रो का विस्तार क्या है, यह जानने के लिए निम्न बैश कमांड देखें gcc -E - <<< $'#include <linux/fs.h>\nFS_IOC_GETFLAGS' | tail -n1। मुझे इससे निम्नलिखित अभिव्यक्ति मिली: (((2U) << (((0 +8)+8)+14)) | ((('f')) << (0 +8)) | (((1)) << 0) | ((((sizeof(long)))) << ((0 +8)+8)))जो कि सरल करता है (2U << 30) | ('f' << 8) | 1 | (sizeof(long) << 16)
रुस्लान

यह पंद्रहवें पर चुटकी लेता है।
रोड शो

@Roadowl वास्तव में। lsattrएक चेतावनी संदेश के साथ उन लोगों को छोड़ देता है। मैंने उन्हें चुपचाप छोड़ने के लिए अपना प्रूफ ऑफ़ कॉन्सेप्ट कोड पैच कर दिया है।
गिल्स एसओ- बुराई को रोकना '

3

मनमाने ढंग से फाइल के नाम (न्यूलाइन वर्ण वाले लोगों सहित) से निपटने के लिए, सामान्य चाल की .//.जगह फाइलों को ढूंढना है .। क्योंकि //सामान्य रूप से निर्देशिका ट्री को ट्रेस करते समय नहीं हो सकता है, आप सुनिश्चित हैं कि एक //संकेत find(या यहाँ lsattr -R) उत्पादन में एक नया फ़ाइल नाम की शुरुआत है ।

lsattr -R .//. | awk '
  function process() {
    i = index(record, " ")
    if (i && index(substr(record,1,i), "i"))
      print substr(record, i+4)
  }
  {
    if (/\/\//) {
      process()
      record=$0
    } else {
      record = record "\n" $0
    }
  }
  END{process()}'

ध्यान दें कि आउटपुट अभी भी अलग हो जाएगा। यदि आपको इसे पोस्ट-प्रोसेस करने की आवश्यकता है, तो आपको इसे अनुकूलित करना होगा। उदाहरण के लिए, आप -v ORS='\0'इसे GNU को खिलाने में सक्षम होने के लिए जोड़ सकते हैं xargs -r0

यह भी ध्यान दें कि lsattr -R(कम से कम 1.42.13) उन फ़ाइलों के झंडे की सूचना नहीं दे सकता है जिनका पथ PATH_MAX से बड़ा है (आमतौर पर 4096) , इसलिए कोई अपनी माता-पिता की निर्देशिका (या पथ के किसी भी घटक) को आगे बढ़ाकर ऐसी अपरिवर्तनीय फ़ाइल को छिपा सकता है - अपने आप को छोड़कर, जैसा कि यह अपरिवर्तनीय है) एक बहुत गहरी निर्देशिका में।

चारों ओर एक काम के findसाथ उपयोग करना होगा-execdir :

find . -execdir sh -c '
  a=$(lsattr -d "$1") &&
    case ${a%% *} in
      (*i*) ;;
      (*) false
    esac' sh {} \; -print0

अब उसके पास -print0 यह पोस्ट-प्रोसेस करने योग्य है, लेकिन यदि आप उन रास्तों के साथ कुछ भी करने का इरादा रखते हैं, तो ध्यान दें कि PATH_MAX से अधिक फ़ाइल पथों पर कोई भी सिस्टम कॉल अभी भी विफल होगा और निर्देशिका घटकों को अंतराल में बदला जा सकता था।

यदि हम एक निर्देशिका ट्री पर एक विश्वसनीय रिपोर्ट प्राप्त करना चाहते हैं जो दूसरों द्वारा संभावित रूप से उपयुक्त है, तो कुछ और मुद्दे अंतर्निहित हैं lsattr कमांड में जो हमें उल्लेख करने की आवश्यकता है:

  • रास्ता lsattr -R . से डायरेक्टरी ट्री को ट्रेस किया जाता है, वह रेस की स्थिति के अधीन है। कोई इसे .सही समय पर सहानुभूति के साथ कुछ निर्देशिकाओं को बदलकर निर्देशिका ट्री के बाहर निर्देशिकाओं में उतर सकता है ।
  • यहां तक lsattr -d fileकि एक दौड़ की स्थिति है। वे विशेषताएँ केवल नियमित फ़ाइलों या निर्देशिकाओं पर लागू होती हैं। तो lsattrएक करता है lstat()यह देखना होगा कि फ़ाइल सही प्रकार की होती है और उसके बाद है पहले open()के बाद ioctl()विशेषताओं को पुनः प्राप्त करने। लेकिन यह open()बिना कॉल O_NOFOLLOW(न ही O_NOCTTY) है। उदाहरण के लिए और सिस्टम को रीबूट fileकरने के /dev/watchdogलिए कोई सिम्लिंक के साथ बदल सकता है । यह दौड़ की स्थितियों से बचने के लिए , और उसके बाद यहां किया जाना चाहिए ।lstat()open()open(O_PATH|O_NOFOLLOW)fstat()openat()ioctl()

2

सही दिशा में मुझे इशारा करने के लिए रमेश, एसएलएम और स्टीफन के लिए धन्यवाद (मैं -Rस्विच को याद कर रहा था lsattr)। दुर्भाग्य से, अब तक किसी भी उत्तर ने मेरे लिए सही ढंग से काम नहीं किया।

मैं निम्नलिखित के साथ आया:

lsattr -aR .//. | sed -rn '/i.+\.\/\/\./s/\.\/\///p'

यह एक फ़ाइल को अपरिवर्तनीय होने के रूप में प्रदर्शित होने के लिए उपयोग की जा रही नई सूचियों से बचाता है, जब यह नहीं है। यह उन फ़ाइलों से रक्षा नहीं करता है जो अपरिवर्तनीय हैं और उनके फ़ाइल नाम में नई सुर्खियाँ हैं। लेकिन चूंकि इस तरह की फाइल को रूट द्वारा बनाया जाना होगा, इसलिए मुझे विश्वास हो सकता है कि मेरे उपयोग के मामले में ऐसी फाइलें मेरे फाइल सिस्टम पर मौजूद नहीं हैं। (यह विधि उन मामलों में घुसपैठ का पता लगाने के लिए उपयुक्त नहीं है जहां रूट उपयोगकर्ता से समझौता किया जा सकता है, लेकिन फिर न तो उसी सिस्टम की lsattrउपयोगिता का उपयोग कर रहा है जो उसी रूट उपयोगकर्ता के स्वामित्व में है।)


केवल रूट ही किसी फ़ाइल में अपरिवर्तनीय बिट को जोड़ सकता है, लेकिन संभावित रूप से अन्य उपयोगकर्ता बाद में पथ घटकों का नाम बदल सकते हैं जो उन फ़ाइलों तक ले जाते हैं, इसलिए फ़ाइल पथ में नई रेखा हो सकती है। इसके अलावा एक उपयोगकर्ता एक फ़ाइल पथ (अपरिवर्तनीय नहीं) बना सकता है जो आपकी स्क्रिप्ट को किसी अन्य फ़ाइल को अपरिवर्तनीय समझने की मूर्खता करेगा।
स्टीफन चेज़लस

2

का उपयोग करते हुए find -exec, बहुत धीमी गति से किया जाता है के उत्पादन को पार्स lsattrहै इसी तरह की है कि अविश्वसनीयls , अजगर में के रूप में प्रयोग गाइल्स से जवाब के लिए निरंतर का चयन करने की आवश्यकता है ioctlकि क्या अजगर दुभाषिया 32- या 64-बिट है पर निर्भर करता है ...

हाथ में समस्या कम या अधिक निम्न-स्तर है, इसलिए निम्न स्तर पर चलते हैं: C ++ स्क्रिप्टिंग भाषा के रूप में उतना बुरा नहीं है :) बोनस के रूप में, इसमें C प्रीप्रोसेसर की पूरी शक्ति के साथ सिस्टम हेडर तक पहुंच है।

निम्न प्रोग्राम अपरिवर्तनीय फ़ाइलों की खोज करता है, एक फाइल सिस्टम के भीतर रहता है, अर्थात कभी भी माउंट पॉइंट्स को पार नहीं करता है। स्पष्ट पेड़ की खोज करने के लिए, आवश्यकतानुसार माउंट बिंदुओं को पार करते FTW_MOUNTहुए, nftwकॉल में ध्वज को हटा दें । इसके अलावा यह सिमिलिंक का पालन नहीं करता है। उनका पालन करने के लिए, FTW_PHYSझंडा हटा दें ।

#define _FILE_OFFSET_BITS 64
#include <iostream>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <sys/stat.h>
#include <ftw.h>

bool isImmutable(const char* path)
{
    static const int EXT3_IMMUTABLE_FLAG=0x10;

    const int fd=open(path,O_RDONLY|O_NONBLOCK|O_LARGEFILE);
    if(fd<=0)
    {
        perror(("Failed to open file \""+std::string(path)+"\"").c_str());
        return false;
    }
    unsigned long attrs;
    if(ioctl(fd,FS_IOC_GETFLAGS,&attrs)==-1)
    {
        perror(("Failed to get flags for file \""+std::string(path)+"\"").c_str());
        close(fd);
        return false;
    }
    close(fd);
    return attrs & EXT3_IMMUTABLE_FLAG;
}

int processPath(const char* path, const struct stat* info, int type, FTW* ftwbuf)
{
    switch(type)
    {
    case FTW_DNR:
        std::cerr << "Failed to read directory: " << path << "\n";
        return 0;
    case FTW_F:
        if(isImmutable(path))
            std::cout << path << '\n';
        return 0;
    }
    return 0;
}

int main(int argc, char** argv)
{
    if(argc!=2)
    {
        std::cerr << "Usage: " << argv[0] << " dir\n";
        return 1;
    }
    static const int maxOpenFDs=15;
    if(nftw(argv[1],processPath,maxOpenFDs,FTW_PHYS|FTW_MOUNT))
    {
        perror("nftw failed");
        return 1;
    }
}

-1

आउटपुट को grep करने के बजाय, आउटपुट के पहले फ़ील्ड में केवल 'i' से मिलान करने के लिए awk का उपयोग क्यों नहीं किया जाता है?

lsattr -Ra 2>/dev/null /|awk '$1 ~ /i/ && $1 !~ /^\// {print}'

वास्तव में, मैं इसे सैकड़ों सर्वरों पर / etc डायरेक्टरी को स्कैन करने और आउटपुट को syslog पर भेजने के लिए क्रोन के माध्यम से चलाता हूं। मैं स्प्लंक के माध्यम से एक दैनिक रिपोर्ट उत्पन्न कर सकता हूं:

lsattr -Ra 2>/dev/null /etc|awk '$1 ~ /i/ && $1 !~ /^\// {print "Immutable_file="$2}'|logger -p local0.notice -t find_immutable

आपके पहले कोड स्निपेट में एक टाइपो है और आपके दूसरे को मेरे सिस्टम पर अपरिवर्तनीय फाइलें नहीं मिली हैं।
21

पहले कमांड में फिक्स्ड टाइपो। शायद दूसरा कोई अपरिवर्तनीय फाइल नहीं ढूंढ रहा है क्योंकि कोई भी नहीं है?
रूटदेव

मैंने ध्यान नहीं दिया कि दूसरी कमांड केवल देख रही थी /etc। लेकिन दोनों आदेशों को गलत तरीके से एक गैर अपरिवर्तनीय के साथ बनाई गई फ़ाइल खोजनेtouch `"echo -e "bogus\n---------i---e-- changeable"`"
depquid

यह मेरी मूल पोस्ट में कहा गया है कि मैं / c आदि निर्देशिका को स्कैन करने के लिए क्रोन के माध्यम से चल रहा हूं। यदि आप इसे चलाने से पहले पोस्ट या कमांड नहीं पढ़ते हैं तो मैं इसकी मदद नहीं कर सकता। और हाँ, आप शायद किसी भी खोज के बारे में बेवकूफ बनाने के लिए एक किनारे मामले का निर्माण कर सकते हैं यदि आप इसे महसूस करते हैं, लेकिन जब से आप अपने मूल कमांड में टाइपो को इंगित करने के लिए बहुत जल्दी थे (अंतिम को याद कर रहे हैं), तो मैं यह इंगित करूंगा कि आपका कमांड लिखित रूप में काम नहीं करता है इसलिए कुछ भी नहीं बनाएगा! :-)
रूटदेव

मेरी गलती। यह कोशिश करें:touch "`echo -e 'bogus\n---------i---e-- changeable'`"
चित्रित करें

-1

बहुत सरल, संदिग्ध फ़ोल्डर में जाएं और कमांड चलाएं:

lsattr -laR | grep *immutable

lsattr -laR | grep + अपरिवर्तनीय
voixip

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