Я настоятельно рекомендую поместить любые нетривиальные задания крона в их собственный файл сценария оболочки по многим причинам:
Причина это не работает, состоит в том, потому что она видит -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 -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"
Ограничение аргумента Linux 2 -(интерпретатор + один аргумент )отмечено в большинстве ответов,но говорить, что это невозможно сделать, неверно — нужно просто перейти на интерпретатор, который может сделать что-то полезное с одним аргументом:
#!/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, оно не будет работать в системе, допускающей несколько аргументов шебанга :-/
perl
обрабатывает эту строку как один аргумент, поэтому она не заключена в кавычки выше, как вы обычно делаете с perl -e...
из командной строки (, если вы добавляете кавычки, они сохраняются, perl видит только литеральная строка с предупреждениями будет жаловаться на бесполезную константу ).
Также обратите внимание, что при таком использовании поведение немного меняется: @ARGV
обычно содержит только аргументы, а $0
содержит скрипт, но с этим шебангом $ARGV[0]
является именем скрипта (и $0
это -e
), что немного упрощает задачу.
Вы также можете решить эту проблему с помощью интерпретатора, который "повторно обрабатывает" свою командную строку (без дополнительного -c
аргумента )древняя AT&T ksh93
делает:
#!/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
для их обработки за один раз.
См. также Множественные аргументы в шебанге для более подробной информации об общей проблеме поведения шебанга.