Napisałem skrypt, który przełącza użytkowników podczas działania, i wykonałem go za pomocą przekierowania plików do standardowego wejścia. Tak więc user-switch.sh
...
#!/bin/bash
whoami
sudo su -l root
whoami
I uruchomienie go bash
daje oczekiwane zachowanie
$ bash < user-switch.sh
vagrant
root
Jeśli jednak uruchomię skrypt sh
, otrzymam inne dane wyjściowe
$ sh < user-switch.sh
vagrant
vagrant
Dlaczego bash < user-switch.sh
daje inną wydajność niż sh < user-switch.sh
?
Uwagi:
- dzieje się na dwóch różnych urządzeniach z systemem Debian Jessie
bash
io-redirection
stdin
dash
popedotninja
źródło
źródło
sudo su
: unix.stackexchange.com/questions/218169/…/bin/sh
na (mojej kopii) Debianie to Dash, tak. Do tej pory nawet nie wiedziałem, co to jest. Do tej pory tkwiłem w bashu.user-switch.sh
w pracy Jenkinsa i skrypt został wykonany. Uruchomienie tego samego skryptu poza Jenkins przyniosło różne wyniki i skorzystałem z przekierowania pliku, aby uzyskać zachowanie, które widziałem w Jenkins.Odpowiedzi:
Podobny skrypt bez
sudo
, ale podobne wyniki:Z
bash
, reszta skryptu idzie jako wejście dosed
, zdash
, na interpretuje ją powłoki.Uruchamianie
strace
na tych:dash
czyta blok skryptu (tutaj osiem kB, więcej niż wystarcza do utrzymania całego skryptu), a następnie odradza sięsed
:Co oznacza, że uchwyt pliku znajduje się na końcu pliku i
sed
nie będzie widział żadnych danych wejściowych. Pozostała część jest buforowana wewnątrzdash
. (Jeśli skrypt był dłuższy niż rozmiar bloku 8 kB, pozostała część zostałaby odczytanased
).Bash natomiast stara się wrócić do końca ostatniego polecenia:
Jeśli dane wejściowe pochodzą z potoku, tak jak tutaj:
przewijanie nie jest możliwe, ponieważ rury i gniazda nie są widoczne. W takim przypadku Bash wraca do czytania jednego znaku na raz, aby uniknąć czytania. (
fd_to_buffered_stream()
ininput.c
) Wykonanie pełnego wywołania systemowego dla każdego bajtu nie jest w zasadzie bardzo skuteczne. W praktyce nie sądzę, aby odczyty były dużym narzutem w porównaniu np. Z faktem, że większość rzeczy, które wykonuje powłoka, obejmuje tworzenie nowych procesów.Podobna sytuacja jest taka:
Podpowłoka musi się upewnić, że
read
czyta tylko pierwsząhead
nową linię , aby zobaczyć następną linię. (To też działadash
.)Innymi słowy, Bash dokłada wszelkich starań, aby obsługiwać czytanie tego samego źródła dla samego skryptu i poleceń z niego wykonywanych.
dash
nie.zsh
Iksh93
pakowany w Debianie iść z Bash w tej sprawie.źródło
strace
później i porównuję wyniki. Nie pomyślałem o takim podejściu.Powłoka odczytuje skrypt ze standardowego wejścia. Wewnątrz skryptu uruchamiasz polecenie, które chce również odczytać standardowe dane wejściowe. Który wkład pójdzie gdzie? Nie możesz rzetelnie powiedzieć .
Powłoki działają tak, że odczytują fragment kodu źródłowego, analizują go, a jeśli znajdą kompletne polecenie, uruchom je, a następnie kontynuuj z pozostałą częścią fragmentu i pozostałą częścią pliku. Jeśli fragment nie zawiera kompletnego polecenia (ze znakiem kończącym na końcu - myślę, że wszystkie powłoki czytają do końca linii), powłoka odczytuje inny fragment i tak dalej.
Jeśli polecenie w skrypcie próbuje odczytać z tego samego deskryptora pliku, z którego powłoka czyta skrypt, to polecenie znajdzie cokolwiek, co nastąpi po ostatnim fragmencie, który przeczytał. Ta lokalizacja jest nieprzewidywalna: zależy od wielkości porcji, którą wybrała powłoka, i może zależeć nie tylko od powłoki i jej wersji, ale także od konfiguracji maszyny, dostępnej pamięci itp.
Bash szuka do końca kodu źródłowego polecenia w skrypcie przed wykonaniem polecenia. Nie jest to coś, na co możesz liczyć, nie tylko dlatego, że inne powłoki tego nie robią, ale także dlatego, że działa to tylko wtedy, gdy powłoka czyta ze zwykłego pliku. Jeśli powłoka odczytuje z potoku (np.
ssh remote-host.example.com <local-script-file.sh
), Odczytane dane są odczytywane i nie można ich odczytać.Jeśli chcesz przekazać dane wejściowe do polecenia w skrypcie, musisz to zrobić jawnie, zwykle w dokumencie tutaj . (Dokument tutaj jest zwykle najwygodniejszy dla wprowadzania wieloliniowego, ale wystarczy dowolna metoda.) Napisany kod działa tylko w kilku powłokach, tylko jeśli skrypt jest przekazywany jako dane wejściowe do powłoki ze zwykłego pliku; jeśli spodziewałeś się, że sekunda
whoami
zostanie przekazana jako dane wejściowe dosudo …
, pomyśl jeszcze raz, pamiętając, że przez większość czasu skrypt nie jest przekazywany do standardowego wejścia powłoki.Pamiętaj, że w tej dekadzie możesz używać
sudo -i root
. Bieganiesudo su
to hack z przeszłości.źródło