Я попробовал следующее, но это не похоже на работу:
$ cat script.sh
#!/bin/env -i /bin/sh
/bin/env
$ script.sh
/bin/env: invalid option -- ' '
Try `/bin/env --help' for more information.
Я попробовал следующее, но это не похоже на работу:
$ cat script.sh
#!/bin/env -i /bin/sh
/bin/env
$ script.sh
/bin/env: invalid option -- ' '
Try `/bin/env --help' for more information.
Ответы:
Причина, по которой это не работает, заключается в том, что он видит -i /bin/shв качестве единственного аргумента env. Обычно это будет 2 аргумента, -iи /bin/sh. Это всего лишь ограничение Шебанга. Обойти это невозможно.
Однако вы все еще можете выполнить эту задачу, просто по-другому.
Если вы хотите, чтобы эта задача выполнялась самим сценарием, и вам не приходилось делать что-то подобное env -i script.sh, вы можете заставить сценарий повторно выполнить сам.
#!/bin/sh
[ -z "$CLEANED" ] && exec /bin/env -i CLEANED=1 /bin/sh "$0" "$@"
Это заставит скрипт повторно выполнить себя, если CLEANEDпеременная окружения не установлена. Затем при повторном запуске он устанавливает переменную, чтобы убедиться, что она не входит в цикл.
envиз GNU coreutils теперь есть возможность -Sобойти проблемы, похожие на эту, но не совсем те же. Например #!/usr/bin/env -S perl -T.
#!/usr/bin/env -S -i /bin/sh. Помните о проблемах переносимости.
Запустите ваш скрипт с env -i:
env -i script.sh
И сценарий как обычно:
#!/bin/sh
# ... your code here
Если вы хотите работать в чистом окружении без явного указания, когда вы запускаете. Эдуардо Иванец (Eduardo Ivanec) дает несколько идей в этом ответе : вы можете рекурсивно вызывать ваш скрипт, execкогда среда не чистая (например, определен $ HOME):
[ "$HOME" != "" ] && exec -c $0
С bash вы можете сделать это так:
#!/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
set -eИ set -u команды не являются строго необходимыми, но я включаю их , чтобы продемонстрировать , что этот подход не зависит от доступа к неустановленные переменные (как , например , [ "$HOME" != "" ]будет) и совместим с set -eустановкой.
Тестирование HOMEпеременной должно быть безопасным, потому что bash выполняет сценарии в неинтерактивном режиме, то есть файлы конфигурации, такие как ~/.bashrc(где могут быть установлены переменные среды), не создаются при запуске.
Пример вывода:
declare -x OLDPWD
declare -x PWD="/home/juser"
declare -x SHLVL="1"
В большинстве ответов отмечается ограничение Шебанга в 2-х аргументах Linux (interpeter + single аргумент), но сказать, что это невозможно, неверно - вам просто нужно перейти к интерпретатору, который может сделать что-то полезное с одним аргументом:
#!/usr/bin/perl -we%ENV=();exec "/bin/sh " . join " ", map "'$_'", @ARGV;
# your sh script here
Что это делает, так это вызывает perlоднострочный скрипт ( -e), который очищает %ENV(дешевле чем env -i) и вызывает exec /bin/sh, правильно цитируя аргументы. При необходимости perlможно добавить дополнительную логику (хотя в Linux не так много, так как вы ограничены BINPRM_BUF_SIZEсимволами, что, вероятно, 128)
К сожалению, это специфично для Linux, оно не будет работать в системе, которая допускает множественные аргументы shebang: - /
perlобрабатывает эту строку как один аргумент, поэтому она не цитируется выше, как вы обычно делаете perl -e ...из командной строки (если вы добавите кавычки, они сохранятся, perl увидит только буквенную строку, а предупреждения на ней будут жаловаться на бесполезную константа).
Также обратите внимание, что при использовании этого способа происходит небольшое изменение в поведении, которое @ARGVобычно содержит только аргументы и $0содержит сценарий, но с этим шебангом $ARGV[0]является имя сценария (и $0есть -e), что делает его немного проще.
Вы также можете решить эту проблему с помощью интерпретатора, который «перерабатывает» свою командную строку (без дополнительного -cаргумента), что ksh93делает древний AT & T :
#!/bin/ksh /usr/bin/env -i /bin/sh
хотя, возможно ksh, не так часто в настоящее время ;-)
( bashимеет аналогичную функцию с --wordexp, но она «недокументирована» в версиях, где она работает, и не включена во время компиляции в версиях, где она документирована: - / Она также не может быть использована для этого, так как для нее требуется два аргумента. ..)
Кроме того, эффективная вариация ответов @Patrick и @ maxschlepzig:
#!/bin/bash
[ "$_" != bash ] && exec -c -a "bash" /bin/bash "$0" "$@"
# your script here
Вместо того, чтобы использовать новую переменную, она использует специальную _переменную " ", если она не установлена точно на "bash", то замените скрипт на execиспользование, -aчтобы сделать ARGV[0](и, следовательно, " $_просто" bash ", и использование -cдля очистки среды.
В качестве альтернативы, если допустимо очищать среду в начале скрипта (только bash):
#!/bin/sh
unset $(compgen -e)
# your script here
Это использует compgen(завершение), чтобы перечислить имена всех экспортируемых переменных окружения, и unsetувидеть их за один раз.
Смотрите также Несколько аргументов в Шебанге для более подробной информации об общей проблеме поведения Шебанга.