Как запустить сценарий с чистой среды?

Я настоятельно рекомендую поместить любые нетривиальные задания крона в их собственный файл сценария оболочки по многим причинам:

  • Легче отладить: можно просто запустить скрипт вместо копии, вставляющей длинную линию, и с правильной строкой хижины, это ведет себя намного больше очевидно, чем если бы у Вас были те же команды непосредственно в crontab
  • Легче читать: никакая потребность сделать это 200 + символьная острота, можно отформатировать его приятно, таким образом, легко читать и понять для всех
  • Добавьте сценарий к управлению версиями
15
05.11.2013, 01:10
5 ответов

Причина это не работает, состоит в том, потому что она видит -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 переменная среды не установлена. Затем на передолжностном лице, это устанавливает переменную, чтобы удостовериться, что это не входит в цикл.

7
27.01.2020, 19:50

Запустите свой скрипт с env -i:

env -i script.sh

И сценарий, как обычно:

#!/bin/sh
# ... your code here

Если Вы означаете работать с чистой средой без, явно говорят это, когда Вы работаете. Eduardo Ivanec дает некоторое представление в этом ответе, можно рекурсивно назвать сценарий с exec когда среда не является чистой (например, $HOME определяется):

[ "$HOME" != "" ] && exec -c $0
3
27.01.2020, 19:50
  • 1
    Хороший. Просто не делайте ENV-i удар как, я сделал и затем задаюсь вопросом, почему Ваши огибающие переменные все еще установлены (конечно, ресурсы удара .bashrc и друзья 8) –  Neil McGill 14.10.2015, 18:35

$ cat script.sh

#!/bin/env -i /bin/sh

Печально это не проложит себе путь — Linux действительно рассматривает -i /bin/sh как один аргумент, который будет передан env (см. Хижину).

0
27.01.2020, 19:50

С 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
27.01.2020, 19:50

Ограничение аргумента 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для их обработки за один раз.

См. также Множественные аргументы в шебанге для более подробной информации об общей проблеме поведения шебанга.

1
27.01.2020, 19:50

Теги

Похожие вопросы