Sytuacja kobiet w IT w 2024 roku
19.01.20216 min
Adam Paszkiewicz
Asseco Poland S.A.

Adam PaszkiewiczTechnology ExpertAsseco Poland S.A.

Jak uzależnić wykonanie skryptu powłoki od systemu operacyjnego dla platform Unix-like

Sprawdź, jak uzależnić shell scripting, czyli wykonanie skryptu powłoki od tego, na jakim systemie operacyjnym dla platform Unix-like pracujemy.

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 Unixa powinien umieć tworzyć skrypty w róż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 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. Oto, 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ę informację, 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órej już wcześniej napomknąłem – systemy operacyjne mogą mieć różne powłoki i nie wszystkie będą w posiadaniu Basha, 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. 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. 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 dwie 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 go rozpoznamy:

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


W przypadku Linuxa 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, pisząc drugi warunek. Następnie sprawdzimy, czy to znana nam dystrybucja Linux, poprzez odczytanie pliku os-release w katalogu /etc (plik ten istnieje również w systemach Red Hat - znajduje się tam zapis o szczegółach dystrybucji np. Oracla Linux). Jeżeli pplik istnieje, to możemy założyć, ż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:

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

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


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.

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


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.

Podsumowanie

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 :)

<p>Loading...</p>