Piszę skrypt powłoki, który powinien być nieco bezpieczny, tj. Nie przekazuje bezpiecznych danych przez parametry poleceń i najlepiej nie używa plików tymczasowych. Jak mogę przekazać zmienną do wejścia standardowego polecenia? A jeśli nie jest to możliwe, jak poprawnie wykorzystać pliki tymczasowe do takiego zadania?
105
$PATH
? Więccat
można to wymienić/bin/cat "$@" | tee /attacker/can/read/this/file
Odpowiedzi:
Coś tak prostego, jak:
źródło
echo "$blah"
jest lepsze.blah=-n
,blah=-e
... stosowanieprintf
zamiast. unix.stackexchange.com/questions/65803/…printf '%s\n' "$blah"
? Z tą jedną zmianą (unikając wiele pułapek wecho
„s specyfikacja, która doskonała odpowiedź Stephane idzie się szczegółowo na Dlaczegoprintf
lepiejecho
? Na Unix i Linux , lub którym sekcja WNIOSEK korzystanie zecho
specyfikacją dotyka więcej krótko) to doskonale rozsądna odpowiedź.Przekazywanie wartości
stdin
w bash jest tak proste, jak:Zawsze upewnij się, że wokół wyrażeń zmiennych umieszczasz cudzysłowy!
źródło
<<<
ma gwarancji, że Herestrings będą dostępne, o ile wiem, nie ma ich w bazie POSIX. Będą działać zgodnie z oczekiwaniami, o ile tylko je uruchomiszbash
. Wspominam o tym tylko dlatego, że OP powiedzieli „shell”, a nie konkretnie „bash”. Chociaż oznaczył pytanie tagiembash
... więc nadal jest to oczywiście akceptowalna odpowiedź.echo
metody ze względu na utworzenie rury. Polecenie herestring zostanie przetworzone w całości przezbash
, chociaż w tej sytuacji (jak wspomniano) lepiej wiedzieć, że będzie działać na twoim bash, w przeciwnym razie każdy komunikat o błędzie powstały w wyniku nieobsługiwania tutaj ciągów również wyciekłby wspomniane informacje.echo
jest wbudowany. Nie ma tam rury, prawda? To Unix, ale to nie może być tak dużo Unix .printf '%s\n' "$var"
daje takie same wyniki, jak,echo "$var"
ale nie zepsuje się , np.var=-en
, I nawet nie wymaga basha.Zauważ, że
echo "$var" | command
operacja ' oznacza, że standardowe wejście jest ograniczone do linii, której (-ych) echo (-ych) zawiera echo. Jeśli chcesz, aby terminal był podłączony, musisz być bardziej wyrafinowany:Oznacza to, że pierwsza linia (wiersze) będzie zawartością,
$var
ale reszta będzie pochodzić zcat
odczytu jego standardowego wejścia. Jeśli polecenie nie robi nic zbyt wymyślnego (spróbuj włączyć edycję wiersza poleceń lub uruchom tak, jakvim
robi), to będzie dobrze. W przeciwnym razie musisz naprawdę polubić - myślę, żeexpect
lub jedna z jego pochodnych może być odpowiednia.Notacje wiersza poleceń są praktycznie identyczne - ale drugi średnik jest konieczny w nawiasach klamrowych, a nie w nawiasach.
źródło
( echo "$LIST"; cat - ) | sed 1q
to działa dla mnie, ale muszę nacisnąć ctrl d po uruchomieniu tego skryptu?cat -
nadal czytać z klawiatury aż do EOF lub przerwać, więc trzeba powiedzieć to EOF wpisując control-D.cat
w ogóle używać, jeśli nie chcesz wprowadzania danych przez terminal, jak w pierwszej linii. Lub możesz użyćcat
do wyświetlenia pliku. Lub ... Jeśli chcesz, aby polecenie odczytywało wejście terminala, musisz powiedzieć mu, kiedy osiągnęło koniec wejścia. Lub możesz użyć( echo "$var"; sed /quit/q - ) | command
; trwa to do momentu wpisania wiersza zawierającego „quit”. Możesz być nieskończenie pomysłowy, jak sobie z tym poradzisz. Uważaj na starą miejską legendę o programie, który przestał działać, gdy użytkownicy zaczęli pracować z Ekwadorem. Wpisywali nazwę stolicy, Quito, i program kończył pracę.echo "$LIST" | sed 1q | ...
? Wszystko zależy od tego, o co ci chodzi.<<EOF
Zapis powinien wymagać EOF na początku linii na własnej gdzieś pliku. Myślę, że nie użyłbym tego - ale nadal nie jestem pewien, co próbujesz osiągnąć. Prostyecho "$LIST" | command
lubecho $LIST | command
prawdopodobnie wystarczy w praktyce (ważne jest, abyś wiedział, jaka jest różnica między nimi).Podobała mi się odpowiedź Martina, ale ma pewne problemy w zależności od tego, co jest w zmiennej. To
jest lepsze, jeśli zmienna zawiera „lub!
źródło
foo1=-; foo2='"'; foo3=\!; cat<<<"$foo1"; cat<<<"$foo2"; cat<<<"$foo3"
dla mnie działa dobrze. Co dokładnie robi ta trójka"
? AFAIK po prostu dodajesz i dołączasz pusty ciąg.Nie
cat
jest to naprawdę potrzebne, ale pomaga w lepszej strukturze kodu i umożliwia użycie większej liczby poleceń w nawiasach jako danych wejściowych do polecenia.źródło
$passwd
Zgodnie z odpowiedzią Martina istnieje funkcja bash o nazwie Here Strings (która sama w sobie jest wariantem szerzej obsługiwanej funkcji Here Documents ).
http://www.gnu.org/software/bash/manual/bashref.html#Here-Strings
Zauważ, że Here Strings wydaje się być tylko bashem, więc dla lepszej przenośności prawdopodobnie lepiej byłoby, gdybyś miał oryginalną funkcję Here Documents, zgodnie z odpowiedzią PoltoS:
Lub prostszy wariant powyższego:
Możesz pominąć
(
i)
, chyba że chcesz, aby to było dalej przekierowywane do innych poleceń.źródło
Ten solidny i przenośny sposób pojawił się już w komentarzach. Powinna to być samodzielna odpowiedź.
lub
Uwagi:
echo
, powody są tutaj: Dlaczego jestprintf
lepsze niżecho
?printf "$var"
jest źle. Pierwszym argumentem jest format, w którym różne sekwencje, takie jak%s
lub\n
są interpretowane . Aby przekazać zmienną w prawo, nie można jej interpretować jako formatu.Zwykle zmienne nie zawierają końcowych znaków nowej linii. Poprzednie polecenie (z
%s
) przekazuje zmienną taką, jaka jest. Jednak narzędzia, które pracują z tekstem, mogą ignorować lub narzekać na niekompletną linię (zobacz Dlaczego pliki tekstowe powinny kończyć się znakiem nowej linii? ). Więc możesz chcieć tego ostatniego polecenia (z%s\n
), które dodaje znak nowego wiersza do zawartości zmiennej. Nieoczywiste fakty:<<<"$var" my_cmd
) dołącza nową linię.my_cmd
, nawet jeśli zmienna jest pusta lub niezdefiniowana.źródło
Spróbuj tego:
źródło
ps -u
echa?echo
jest wbudowany, więc nie ma procesu do wyświetlenia w psecho "$variable"
jest lepsze.Po prostu zrób:
Jeśli zmienna nie zawiera spacji, cudzysłowy można pominąć.
Jeśli używasz basha, możesz również:
Unikaj używania echo bez -n, ponieważ spowoduje to potokowanie vraiable z dodanym podziałem wiersza na końcu.
źródło
%s
, printf niczego nie wydrukuje.my_var="%s"; printf "$my_var";
- może spróbowaćprintf "%s" "$my_var" | my_cmd
?