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.
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.
Odpowiedzi:
Powodem tego nie jest to, że traktuje to -i /bin/shjako pojedynczy argument env. Zwykle byłyby to 2 argumenty -ii /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.
#!/bin/sh
[ -z "$CLEANED" ] && exec /bin/env -i CLEANED=1 /bin/sh "$0" "$@"
Spowoduje to ponowne wykonanie skryptu, jeśli CLEANEDzmienna środowiskowa nie jest ustawiona. Następnie przy ponownym wykonaniu ustawia zmienną, aby upewnić się, że nie przechodzi ona w pętlę.
envz jądra GNU mają teraz możliwość -Sobejś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:
env -i script.sh
I skrypt jak zwykle:
#!/bin/sh
# ... your code here
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, execgdy środowisko nie jest czyste (np. Zdefiniowano $ HOME):
[ "$HOME" != "" ] && exec -c $0
Dzięki bash możesz to zrobić w następujący sposób:
#!/usr/bin/bash
set -e
set -u
[ -v HOME ] && exec -c "$0" "$@"
# continue with the rest of the script
# e.g. print the cleaned environment:
export
Polecenia set -ei set -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 z set -eustawieniem.
Testowanie HOMEzmiennej 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:
declare -x OLDPWD
declare -x PWD="/home/juser"
declare -x SHLVL="1"
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:
#!/usr/bin/perl -we%ENV=();exec "/bin/sh " . join " ", map "'$_'", @ARGV;
# your sh script here
Co to robi to invoke perlze skryptem jedną liniowej ( -e), która czyści %ENV(tańsze niż env -i) i wywołuje exec /bin/sh, właściwego zacytowania argumentów. W perlrazie potrzeby można dodać dalszą logikę (choć niewiele w Linuksie, ponieważ jesteś ograniczony do BINPRM_BUF_SIZEznakó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: - /
perlprzetwarza ten ciąg jako pojedynczy argument, więc nie jest cytowany powyżej, jak to zwykle bywało z perl -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, @ARGVzwykle zawiera tylko argumenty i $0skrypt, ale z tym shebangiem $ARGV[0]jest nazwa skryptu (i $0jest -e), co czyni to trochę łatwiejszym.
Możesz również rozwiązać ten problem za pomocą interpretera, który „przetwarza” linię poleceń (bez dodatkowego -cargumentu), co starożytne AT&T ksh93:
#!/bin/ksh /usr/bin/env -i /bin/sh
choć może kshnie jest tak powszechne w dzisiejszych czasach ;-)
( bashma 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:
#!/bin/bash
[ "$_" != bash ] && exec -c -a "bash" /bin/bash "$0" "$@"
# your script here
Zamiast używać nowy Zmienna ta wykorzystuje specjalne „ _” zmienna, jeśli nie jest ustawiona dokładnie „bash”, a następnie zastąpić skrypt z execużyciem -azrobić ARGV[0](i stąd $_) tylko „bash”, a przy użyciu -coczyścić środowisko.
Alternatywnie, jeśli dopuszczalne jest czyszczenie środowiska na początku skryptu (tylko bash):
#!/bin/sh
unset $(compgen -e)
# your script here
Wykorzystuje compgen(pomocnik uzupełniania), aby wyświetlić listę nazw wszystkich eksportowanych zmiennych środowiskowych, i unsets je za jednym razem.
Zobacz także Wiele argumentów w shebang, aby uzyskać więcej informacji na temat ogólnego problemu zachowania shebang.