Czasami zachodzi potrzeba uruchomienia z naszego programu/skryptu pythonowego skryptu w Bashu. Oczywiście, można byłoby całą funkcjonalność tego skryptu przepisać w Pythonie, jednak czasami musimy użyć takiego rozwiązania i wtedy świetnie byłoby, gdyby można było odczytać kod powrotu skryptu bashowego.
W poniższym przykładzie mamy skrypt w Bashu, który sprawdza czy plik testfile istnieje w bieżącym katalogu. Jeśli istnieje, zwraca wartość 0, jeśli nie, zwraca 1. Dodatkowo dodałem kilka sleepów i skrypt wypisuje na ekranie ilość sekund do wywołania sprawdzenia.
sleep.sh:
#!/bin/bash PLIK="./testfile" echo "3" sleep 1 echo "2" sleep 1 echo "1" sleep 1 if [ -e $PLIK ]; then exit 0 else exit 1 fi |
W skrypcie pythonowym importujemy moduł subprocess, który umożliwia uruchamianie nowych procesów, podłączanie się do ich potoków wejścia, wyjścia i błędu oraz uzyskiwanie ich kodu powrotu.
Ze względów bezpieczeństwa zaleca się ustawienie parametru shell=False. Więcej informacji na ten temat można przeczytać tutaj.
Jeżeli potrzebujemy bardziej zaawansowanych opcji, warto użyć klasy Popen z modułu subprocess.
runbash.py:
#!/usr/bin/env python2 import subprocess print('start') if (subprocess.call('./sleep.sh', shell=False) == 0): print('plik istnieje') else: print('plik nie istnieje') print('koniec') |
uruchomienie:
[bart@fedora20 python]$ ./runbash.py start 3 2 1 plik nie istnieje koniec [bart@fedora20 python]$ touch testfile [bart@fedora20 python]$ ./runbash.py start 3 2 1 plik istnieje koniec [bart@fedora20 python]$ |
opis działania:
Przy pierwszym uruchomieniu w lokalnym katalogu nie było pliku testfile:
1. Skrypt runbash.py wywołał podproces sleep.sh
2. Instrukcja warunkowa if/else w sleep.sh sprawdziła, że plik nie istnieje i skrypt zakończył się z kodem powrotnym 1.
3. Instrukcja warunkowa if/else w runbash.py odczytała kod powrotny z sleep.sh (1) i wyświetliła na ekranie komunikat z informacją, że plik nie istnieje.
Przed drugim uruchomieniem utworzyliśmy plik testfile (touch testfile), sleep.sh zakończył się z kodem powrotu 0. Kod powrotu został odczytany przez runbash.py i skrypt wyświetlił informację, że plik istnieje.