borzole Napisano Lipiec 3, 2010 Zgłoszenie Share Napisano Lipiec 3, 2010 Witam, udało mi się wreszcie napisać "coś" w pythonie i to z gtk (jupi!), no ale to wszystko wyglądało tak magicznie, że miałbym prośbę, potrzebuję: * chętnych do przetestowania, czy jakieś głupoty nie wyskakują tam gdzie nie potrzeba * chętnych do przejrzenia kodu (miernik WTF 'mile' widziany) skrypt: sudog.py Jak testować: * na początku skryptu zmienić w klasie SudoSimple tę linię: sudoers='/home/lucas/project/python/sudo/sudoers' na ścieżkę absolutną do kopi pliku /etc/sudoers * proszę pamiętać o prawach dostępu i właścicielu (chmod,chown) Tak na marginesie: Dla roota nawet pliki tylko do odczytu, są zapisywalne ! Czy to normalne? Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
ecik__ Napisano Lipiec 3, 2010 Zgłoszenie Share Napisano Lipiec 3, 2010 Później zerknę dokładniej na kod, ale najpierw: * na początku skryptu zmienić w klasie SudoSimple tę linię: sudoers='/home/lucas/project/python/sudo/sudoers' na ścieżkę absolutną do kopi pliku /etc/sudoers * proszę pamiętać o prawach dostępu i właścicielu (chmod,chown) Jeśli chodzi o pierwszy punkt to może wygodniej byłoby zrobić jakiegoś file choosera albo dać to do configa? Co do drugiego, proponuję zrobić obsługę wyjątków i zgłoszenie odpowiedniego komunikatu, gdy któregoś z uprawnień brakuje. [edit] Ok, spojrzałem w kod i mam takie uwagi: rozbijanie tego wyrażenia regularnego na szereg dodatkowych zmiennych IMO znacznie obniża jego czytelność i zwiększa podatność na błędy (których się nie ustrzegłeś). Można to zrobić np. tak: passwd="^\s*%s\s+ALL\s*=\s*\(\s*ALL\s*\)\s*ALL\s*$" i potem korzystając z operatora % podstawiać tam nazwę usera, przykład: In [41]: passwd="^\s*%s\s+ALL\s*=\s*\(\s*ALL\s*\)\s*ALL\s*$" In [42]: print passwd % 'ecik' ^\s*ecik\s+ALL\s*=\s*\(\s*ALL\s*\)\s*ALL\s*$ Zrobić też trzeba oczywiście podobne wyrażenie dla NOPASSWD - choć tak naprawdę wystarczy zrobić jedno wyrażenia dla obu typów, a potem z pomocą grup będzie się dało rozróżnić które wyrażenie zostało zastosowany - służę pomocą, jakby co A jeśli uważasz, że tamto wyrażenie regularne jest nieczytelne to można je ładnie "uczytelnić" korzystając z flagi verbose (x), którą można zapodać w wyrażeniu. Wtedy wyrażenie mogłoby wyglądać np. tak: passwd = r""" (?x) # ustawiamy flagę VERBOSE ^\s* # początek stringu i dowolna ilość białych znaków %s # tu zostanie podstawiona nazwa usera \s+ ALL # co najmniej jeden biały znak i słówko 'ALL' \s*=\s* # znak '=' z otoczeniem \(\s* ALL \s*\) \s* ALL \s* $ # koniec linii """ Polecam poczytać helpa do re - daje naprawdę olbrzymie możliwości if re.search(passwd, line) != None: Jak sprawdzasz czy dany obiekt jest typu None to właściwie powinieneś używać operatora is. Zaś najlepiej, w ogóle do niczego tutaj nie porównać wyniku searcha tylko zrobić tak: if re.search(passwd, line): Polecam poczytać w dokumentacji jakie wyrażenia są rozpoznawane jako prawdziwe, a jakie jako fałszywe. #@TODO: czy można edytować plik 'w locie', bez dwukrotnego otwarcia? Można, przy otwieraniu pliku trzeba podać r+ jako flagi, ale nie osiągniesz w ten sposób tego co chcesz. Można też użyć modułu fileinput, używając przy tworzeniu obiektu parametru inplace. Podanie tego parametru powoduje, że sys.stdout jest przekierowywany na plik i wywołanie print zapisuje do pliku. Np. poniższy kodzik powoduje usunięcie z pliku tekstowego wszystkich linii zaczynających się literą 'a': import fileinput file = fileinput.input('test', inplace=1) for line in file: if not line.startswith('a'): print line, Zwracam uwagę na przecinek na końcu linii z print. Powoduje on, że print nie dopisuje nowej linii (co jest pożądane gdyż "\n" jest uwzględniany w line). Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
borzole Napisano Lipiec 4, 2010 Autor Zgłoszenie Share Napisano Lipiec 4, 2010 Dzięki za odpowiedź. * Plik jest jeden: /etc/sudoers więc nie ma sensu go wybierać z programu natomiast sprawdzania praw dostępu na razie mi się nie chciało robić, potem pomyślę. * Dzięki za wskazówki do re. Nie wiedziałem, że można tam jakieś parametry i komentarze wrzucać. Natomiast wytłumacz mi co masz na myśli mówiąc "grupy". Zrobiłem to teraz tak, że przeniosłem do funkcji: def rex(self,name,data=None): sudo = r""" (?x) # ustawiamy flagę VERBOSE # borzole ALL=(ALL) ALL # lucas ALL=(ALL) NOPASSWD:ALL ^\s* # początek stringu i dowolna ilość białych znaków %s # tu zostanie podstawiona nazwa usera \s+ ALL # co najmniej jeden biały znak i słówko 'ALL' \s*=\s* # znak '=' z otoczeniem \(\s* ALL \s*\) # %s # podstawić \s*NOPASSWD\s*:\s* \s* ALL \s* # $ # koniec linii """ if data : return sudo % (name,"\s*NOPASSWD\s*:\s*") else: return sudo % (name,"") i odwołanie jest tak: def get(self,name): passwd = self.rex(name) nopasswd = self.rex(name,True) # nie tyle 'True' co właściwie cokolwiek ale oczywiście, chciałbym zobaczyć Twoją propozycję. Zaktualizowałem skrypt pod tym samym linkiem, jakbyś miał ochotę to drąż dalej. Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
ecik__ Napisano Lipiec 4, 2010 Zgłoszenie Share Napisano Lipiec 4, 2010 * Dzięki za wskazówki do re. Nie wiedziałem, że można tam jakieś parametry i komentarze wrzucać. Natomiast wytłumacz mi co masz na myśli mówiąc "grupy". Zrobiłem to teraz tak, że przeniosłem do funkcji: Grupy to fragment wyrażenia regularnego, który umieszczasz w nawiasach i później możesz wyciągnąć jego zawartość. Wcześniej dużo tworzyłeś skryptów bashowych to na pewno wiesz o co chodzi Przykład: In [26]: regex = ('^(\w+)\s*=\s*(\d+)$') In [27]: re.search (regex, 'sdd =427').groups() Out[27]: ('sdd', '427') In [28]: re.search (regex, 'sdd =427').group(1) Out[28]: 'sdd' Groups wyciąga wszystkie grupy, group - jedną konkretną. Można przerobić to wyrażenie regularne z sudog do takiej postaci: sudo = r""" (?x) # ustawiamy flagę VERBOSE # borzole ALL=(ALL) ALL # lucas ALL=(ALL) NOPASSWD:ALL ^\s* # początek stringu i dowolna ilość białych znaków %s # tu zostanie podstawiona nazwa usera \s+ ALL # co najmniej jeden biały znak i słówko 'ALL' \s*=\s* # znak '=' z otoczeniem \(\s* ALL \s*\) # (\s*NOPASSWD\s*:)? # NOPASSWD co najwyżej jeden raz \s* ALL \s* # $ # koniec linii """ i taki przykładowy kod funkcji do pobierania typu: def get_type(user, line): sudore = re.compile(sudo % user) m = sudore.match(line) if m: if m.group(1) is not None: # czyli zawiera ciąg NOPASSWD return 'nopasswd' else: return 'passwd' else: return None I później taki kod print get_type('borzole', 'borzole ALL=(ALL) ALL') print get_type('borzole', 'borzole ALL=(ALL) NOPASSWD:ALL') print get_type('borzole', 'borzole ALL=(ALL) NOPASWD:ALL') zwróci: passwd nopasswd None Dzięki temu jest tylko jedno wyrażenie regularne, które spróbuje dopasować linię, a potem z jego wykorzystaniem można sprawdzić czy była to linia z NOPASSWD czy bez tego Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
borzole Napisano Lipiec 12, 2010 Autor Zgłoszenie Share Napisano Lipiec 12, 2010 Dobra, nie chciało mi się już za bardzo przy tym grzebać, tylko po to żeby bylo "ładnie". Dzięki za wskazówki, wykorzystam przy następnych pomysłach. Ostateczna wersja skryptu: jedral.one.pl/search/label/sudog Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Rekomendowane odpowiedzi
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto
Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.
Zarejestruj nowe konto
Załóż nowe konto. To bardzo proste!
Zarejestruj sięZaloguj się
Posiadasz już konto? Zaloguj się poniżej.
Zaloguj się