Próbowałem następujące, ale wydaje się, że nie działa:
$ cat script.sh
#!/bin/env -i /bin/sh
/bin/env
$ script.sh
/bin/env: invalid option -- ' '
Try `/bin/env --help' for more information.
bash
shell-script
env
balki
źródło
źródło
Odpowiedzi:
Powodem tego nie jest to, że traktuje to
-i /bin/sh
jako pojedynczy argumentenv
. Zwykle byłyby to 2 argumenty-i
i/bin/sh
. To tylko ograniczenie shebang. Nie da się tego obejść.Jednak nadal możesz wykonać to zadanie, po prostu w inny sposób.
Jeśli chcesz, aby to zadanie zostało wykonane przez sam skrypt i nie musisz robić czegoś takiego
env -i script.sh
, możesz ponownie uruchomić skrypt.Spowoduje to ponowne wykonanie skryptu, jeśli
CLEANED
zmienna środowiskowa nie jest ustawiona. Następnie przy ponownym wykonaniu ustawia zmienną, aby upewnić się, że nie przechodzi ona w pętlę.źródło
env
z jądra GNU mają teraz możliwość-S
obejścia problemów podobnych do tego, ale nie dokładnie takich samych. Na przykład#!/usr/bin/env -S perl -T
.#!/usr/bin/env -S -i /bin/sh
. Pamiętaj o problemach z przenośnością.Uruchom skrypt za pomocą
env -i
:I skrypt jak zwykle:
Jeśli chcesz uruchomić w czystym środowisku, nie mówiąc wprost o tym podczas uruchamiania. Eduardo Ivanec podaje kilka pomysłów w tej odpowiedzi , możesz rekurencyjnie wywoływać skrypt,
exec
gdy środowisko nie jest czyste (np. Zdefiniowano $ HOME):źródło
Dzięki bash możesz to zrobić w następujący sposób:
Polecenia
set -e
iset -u
nie są absolutnie konieczne, ale dołączam je, aby wykazać, że to podejście nie polega na uzyskiwaniu dostępu do nieuzbrojonych zmiennych (jak np.[ "$HOME" != "" ]
) I jest zgodne zset -e
ustawieniem.Testowanie
HOME
zmiennej powinno być bezpieczne, ponieważ bash wykonuje skrypty w trybie nieinteraktywnym, tzn. Pliki konfiguracyjne takie jak~/.bashrc
(gdzie można ustawić zmienne środowiskowe) nie są pozyskiwane podczas uruchamiania.Przykładowe dane wyjściowe:
źródło
Niestety nie zadziała w ten sposób - Linux uważa,
-i /bin/sh
że należy przekazać jeden argumentenv
(patrz Shebang ).źródło
W większości odpowiedzi odnotowano ograniczenie linuksowego 2-argumentowego ograniczania (interpeter + pojedynczy argument), ale stwierdzenie, że nie można tego zrobić, jest niepoprawne - wystarczy zmienić na interpretera, który może zrobić coś użytecznego za pomocą jednego argumentu:
Co to robi to invoke
perl
ze skryptem jedną liniowej (-e
), która czyści%ENV
(tańsze niżenv -i
) i wywołujeexec /bin/sh
, właściwego zacytowania argumentów. Wperl
razie potrzeby można dodać dalszą logikę (choć niewiele w Linuksie, ponieważ jesteś ograniczony doBINPRM_BUF_SIZE
znaków, co prawdopodobnie wynosi 128)Niestety, jest to specyficzne dla Linuksa, nie będzie działać w systemie, który pozwala na wiele argumentów shebang: - /
perl
przetwarza ten ciąg jako pojedynczy argument, więc nie jest cytowany powyżej, jak to zwykle bywało zperl -e ...
linii poleceń (jeśli chcesz dodać cudzysłowy, są one zachowane, perl widzi tylko dosłowny ciąg, z ostrzeżeniami narzeka na bezużyteczne stały).Zauważ też, że przy takim stosowaniu zachowuje się niewielka zmiana,
@ARGV
zwykle zawiera tylko argumenty i$0
skrypt, ale z tym shebangiem$ARGV[0]
jest nazwa skryptu (i$0
jest-e
), co czyni to trochę łatwiejszym.Możesz również rozwiązać ten problem za pomocą interpretera, który „przetwarza” linię poleceń (bez dodatkowego
-c
argumentu), co starożytne AT&Tksh93
:choć może
ksh
nie jest tak powszechne w dzisiejszych czasach ;-)(
bash
ma podobną funkcję--wordexp
, ale jest „nieudokumentowany” w wersjach, w których działa, i nie jest włączony w czasie kompilacji w wersjach, w których jest udokumentowany: - / Nie można go również użyć do tego, ponieważ wymaga dwóch argumentów. ..)Również skutecznie odmiana odpowiedzi @Patrick i @ maxschlepzig:
Zamiast używać nowy Zmienna ta wykorzystuje specjalne „
_
” zmienna, jeśli nie jest ustawiona dokładnie „bash”, a następnie zastąpić skrypt zexec
użyciem-a
zrobićARGV[0]
(i stąd$_
) tylko „bash”, a przy użyciu-c
oczyścić środowisko.Alternatywnie, jeśli dopuszczalne jest czyszczenie środowiska na początku skryptu (tylko bash):
Wykorzystuje
compgen
(pomocnik uzupełniania), aby wyświetlić listę nazw wszystkich eksportowanych zmiennych środowiskowych, iunset
s je za jednym razem.Zobacz także Wiele argumentów w shebang, aby uzyskać więcej informacji na temat ogólnego problemu zachowania shebang.
źródło