Wybierz region
pl
  • PL
  • EN
Wydrukuj

Shell Scripting w przykładach: jak uzależnić wykonanie skryptu powłoki od systemu operacyjnego dla platform Unix-like

Zacznijmy od tego, że każdy rasowy administrator systemów operacyjnych wywodzących się z Unix’a powinien umieć tworzyć skrypty w rożnych powłokach. Oczywiście coraz częściej i szerzej administratorzy korzystają z potęgi języków programowania takich jak Python, które dają bardzo wiele możliwości jednak wiele rzeczy można szybko i bezproblemowo oprogramować korzystając z potencjału jakie daje możliwość programowania w powłokach.

Zaprawdę powiadam Wam, że w większości przypadków nie ma sensu strzelać do wróbla z armaty i tworzyć potworów. Ja osobiście staram się być wierny starej regule o bardzo wdzięcznej nazwie KISS czyli Keep It Simple, Stupid – co w moim rozumieniu oznacza rób to co masz do zrobienia w maksymalnie prosty sposób.  I jeszcze jedno - chociaż nie wszyscy się z tym zgadzają – tworzenie skryptów shell jest również programowaniem … kropka.

To wróćmy do Shells. Oczywiście jest wiele powłok jednak obecnie najczęściej stykamy się z Bash czyli Bourne-Again Shell, która w większości Linuxów jest standardem oraz Ksh innymi słowy Korn Shell -  ze względu na  starsze systemy jak AIX czy też HP-UX, które Ksh używają jako powłoki podstawowej. Oczywiście nie należy zapominać o podstawowej sh (Bourne Shell) dostępnej na wszystkich systemach uniksopodobnych.

Każda z powłok ma swoją specyfikę jednak  - w tym artykule - nie będziemy się skupiać na tychże, a raczej musimy brać je pod uwagę ze względu na to o czym wspomniałem czyli standard dla systemu operacyjnego.

Zacznijmy od przedstawienia problemu czyli na czym polega nasz przykład i co chcemy w nim osiągnąć:  mamy za zadanie sprawdzenie błędnych logowań do systemu operacyjnego w celu ich monitorowania. Wybrałem taki przykład ze względu na to, że każdy system operacyjny jest specyficzny, a jego specyfika - patrząc przez prymat zadania - polega na tym, że logi w których odkładają się informacje o logowaniach znajdują się w różnych miejscach i mają różne nazewnictwo. Oczywiście można logować się na każdy host i wykonywać polecenie, które wyciągnie interesujące nas dane jednak my stworzymy jeden prosty skrypt, który rozpozna z jakiej rodziny wywodzi się system operacyjny, a mając tą informacje wywoła odpowiednie polecenie na tym logu, które wskaże próby nieprawidłowych logowań.

Przedstawmy zatem podział systemów operacyjnych jaki jest nam niezbędny do wykonania zadania wraz z lokalizacją i nazewnictwem interesującego nas logu:

  • Red Hat (RHEL, CentOS, Oracle Linux) - /var/log/secure
  • Debian (Debian, Ubuntu) - /var/log/auth.log
  • Solaris - /var/log/authlog
  • AIX - /var/log/messages
  • HP-UX - /var/adm/syslog/syslog.log
  • Vmware - /var/log/auth.log

To tyle jeżeli chodzi o to skąd wyciągnąć informację. Od razu mogę zastrzec, że badane są tylko takie systemy ponieważ akurat takimi dysponowałem w razie potrzeby można dopisać kolejne.

Przystąpmy do działania.

Pierwsza rzecz o której musimy pamiętać i o którym już wcześniej napomknąłem – systemy operacyjne mogą mieć różne powłoki i nie wszystkie będą w posiadaniu Bash’a więc składnia, dla tego konkretnego przypadku, musi spełniać warunki wykonania na powłoce Bourne Shell czyli sh. Dlaczego? Tutaj musimy mieć wiedzę odnośnie systemów operacyjnych i wykorzystywanych przez nie powłok, a w jeżeli chodzi o nasz przykład to z Bourne Shell (sh) korzysta Vmware (i jest dostępny na wszystkich innych systemach związanych z UNIX).

W przypadku, gdy piszemy skrypt przeznaczony do pracy na wielu systemach i różnych powłokach nie należy podawać w shebang line (czyli na początku skryptu) ścieżki do konkretnej powłoki – domyślnie skorzysta z Bourne Shell (sh). Można skorzystać ze składni:

#!/usr/bin/env sh
Co dalej? Zajmijmy się znalezieniem rodziny systemu operacyjnego no i dla porządku nazwy hosta. Skorzystam tutaj z polecenia uname -a, którego wywołanie  wygląda dla przykładu:

[aciek@nielot os_scripts_and_configs]$ uname -a

Linux nielot 3.10.0-1160.2.1.el7.x86_64 #1 SMP Tue Oct 6 10:02:36 PDT 2020 x86_64 x86_64 x86_64 GNU/Linux

aciek@solaris:~$ uname -a

SunOS solaris 5.11 11.3 i86pc i386 i86pc

Powyżej mamy wyniki polecenia uname z dwóch systemów operacyjnych: Linux oraz Solaris. Oczywiście na innych wygląda nieco inaczej ale uname -a działa na każdym z Unix-like systemów operacyjnych.

Wróćmy do naszego programu. Do wyciągnięcia danych skorzystam z języka AWK, którego zastosowania zademonstruję w innym artykule z serii Shell Scripting w przykładach. Składnia z której skorzystam wygląda następująco:

SYSTEM=$(uname -a |awk ' { print $1 }')

NAME=$(uname -a |awk ' { print $2 }')

Oczywiście w przypadku nazwy hosta można skorzystać z innych poleceń jak na przykład hostname ale to już według uznania.

 No dobrze, teraz podzielimy systemy na 2 gałęzie: Linux oraz wszystkie inne Unix-like. Wykorzystamy do tego dane które przypisaliśmy do zmiennej SYSTEM. Jeżeli chodzi o to co Linuxem nie jest to mamy jasną sytuację. Każdy system w polu pierwszym polecenia uname -a ma unikalny identyfikator po którym do rozpoznamy:

  • SunOS to Solaris
  • AIX to AIX
  • Hpux to HP-UX
  • VMkernel to VmWare

W przypadku systemu Linux polecenie uname pokazuje nam string „Linux” niezależnie od dystrybucji. Musimy zdobyć niezbędną dla nas informację czyli to z jakiej rodziny dystrybucja się wywodzi bo to wiąże się z lokalizacją logów. Na potrzeby naszego przypadku potrzebujemy wiedzieć czy dystrybucja, którą badamy, jest pochodną Red Hat czy też Debiana. Wszystkie dystrybucje Linux, które wywodzą się od Red Hat mają w katalogu /etc plik o nazwie redhat-release. Jeżeli taki plik nie występuje dystrybucja ma inne pochodzenie. Z tego skorzystamy w drugim warunku czyli co Red Hat’em nie jest. Czy to z całą pewnością znana nam dystrybucja Linux sprawdzamy poprzez kontrolę pliku os-release w katalogu /etc (oczywiście w systemach Red Hat również występuje gdzie znajduje się zapis o szczegółach dystrybucje np. Oracle Linux). Na nasze potrzeby zakładamy, że to Debian (chociaż wiem, że i Suse korzysta z tego pliku). W razie potrzeby można tutaj doczytać informację o dokładnej dystrybucji z os-release jednak dla naszego programu jest to zbędne.

W tym momencie wystarczy przy konkretnych warunkach, które rozpoznają system lub dystrybucję wstawić polecenia wyszukujące czyli grep dla stringu Failed w odpowiednich logach i winniśmy otrzymać wyniki. Składnia powinna  wyglądać następująco:

if [ $SYSTEM = "Linux" ]

then

if [ -f /etc/redhat-release ]

then

cat /var/log/secure|grep "Failed"

else

if [ -f /etc/os-release ]

then

cat /var/log/auth.log|grep "Failed"

else

echo "Unknown Linux Distribution"

fi

fi

else

if [ $SYSTEM = "SunOS" ]

then

cat /var/log/authlog|grep "Failed"

fi

 

if [ $SYSTEM = "AIX" ]

then

cat /var/log/messages|grep "Failed"

fi

 

if [ $SYSTEM = "HP-UX" ]

then

cat /var/adm/syslog/syslog.log|grep "Failed"

fi

 

if [ $SYSTEM = "VMkernel" ]

then

cat /var/log/auth.log|grep "Failed"

fi

fi

Oczywiście moglibyśmy jeszcze sprawdzać czy istnieje plik logu w danej lokalizacji ale w jaki sposób to zrobić przedstawię w innym przykładzie.

Możemy teraz zawołać nasz skrypt. Z racji tego, że będziemy sięgać do logów systemowych aby mieć do nich uprawnienia należy użyć sudo.

aciek@nielot os_scripts_and_configs]$ sudo ./check_failed.sh

Linux nielot

FAILED LOGIN

Dec  2 22:04:26 nielot sshd[1932]: Failed password for aciek from 192.168.0.100 port 62632 ssh2

Dec  2 22:04:30 nielot sshd[1932]: Failed password for aciek from 192.168.0.100 port 62632 ssh2

Dec  2 22:04:33 nielot sshd[1932]: Failed password for aciek from 192.168.0.100 port 62632 ssh2

Skrypt można również zawołać zdalnie przez ssh np. ssh root@server  < check_failed.sh pamiętając o tym, że potrzebujemy odpowiednich uprawnień aby móc czytać logi lub innymi sposobami chociażby via Rundeck.

Podsumowując to skrypty shell są naprawdę fajne i dość proste, a ich podstawy winien znać każdy, kto cokolwiek robi w systemach Unix-like. I tutaj możemy dojść do dość prostego wniosku: jeżeli znasz system operacyjny i jego polecenia to nie ma problemu aby z nich skorzystać tworząc skrypty, które zapewne ułatwią Ci życie. I jeszcze jedno można robić różne cuda na kiju i wodotryski – jednak nie zapomnijmy o podstawach - no i oczywiście o regule KISS ????.

Do zobaczenia i niech Shell będzie z Wami :)


Adam Paszkiewicz

Adam aka aciek, Ekspert ds. Technologii z Asseco Warszawa. Z technologiami związany od okresu dojrzewania (a ten był dawno temu) ale gotować i żeglować też potrafi. Rzeczy niemożliwe realizuje od ręki, na cuda trzeba chwilę zaczekać. Uważa, że w życiu jak i w pracy dobrze mieć kupę radości ... z przewagą radości.


Wydrukuj