Я определил функцию оболочки (давайте назовем ее clock
), которую я хочу использовать в качестве оболочки для другой команды, аналогично time
функции, например clock ls -R
.
Моя функция оболочки выполняет некоторые задачи и затем заканчивается на exec "$@"
.
Мне бы хотелось, чтобы эта функция работала даже со встроенными оболочками, например, clock time ls -R
должна выводить результат time
встроенной функции, а не /usr/bin/time
исполняемый файл. Но exec
всегда заканчивается тем, что запускает команду.
Как я могу заставить мою функцию Bash работать как оболочка, которая также принимает встроенные функции оболочки в качестве аргументов?
Редактировать : я только что узнал, что time
это не встроенный Bash, а специальное зарезервированное слово, относящееся к конвейерам. Мне все еще интересно решение для встроенных модулей, даже если оно не работает time
, но более общее решение было бы еще лучше.
источник
exec bash -c \' "$@" \'
. Если ваша команда в первом параметре не будет распознана как сценарий оболочки, она будет интерпретироваться как двоичный файл для непосредственного запуска. В качестве альтернативы, и более просто, просто пропуститеexec
и вызов"@"
из вашей оригинальной оболочки.Ответы:
Вы определили функцию bash. Таким образом, вы уже находитесь в оболочке bash при вызове этой функции. Таким образом, эта функция может выглядеть так:
Эта функция может быть вызвана с помощью встроенных команд bash, специальных зарезервированных слов, команд и других определенных функций:
Псевдоним:
Встроенный Bash:
Еще одна функция:
Исполняемый файл:
источник
$@
иexec $@
, если я знаю, что я выполняю фактическую команду?exec
, команда заменяет оболочку. Следовательно, больше нет встроенных элементов, псевдонимов, специальных зарезервированных слов, определенных слов, потому что исполняемый файл выполняется с помощью системного вызоваexecve()
. Этот системный вызов ожидает исполняемый файл.exec $0
есть один процесс, а$@
еще два.$@
имеет запущенную оболочку в качестве родителя и команду в качестве дочернего процесса. Но когда вы хотите использовать встроенные функции, псевдонимы и так далее, вы должны сохранить оболочку. Или начать новый.Единственный способ запустить встроенную оболочку или ключевое слово shell - это запустить новую оболочку, потому что exec «заменяет оболочку данной командой». Вы должны заменить свою последнюю строку на:
Это работает как со встроенными, так и зарезервированными словами; принцип тот же.
источник
Если оболочка должна вставить код перед данной командой, псевдоним будет работать, поскольку они раскрываются на очень ранней стадии:
Псевдонимы почти буквально вставляются вместо псевдонима, поэтому конечный элемент
;
важен - онclock time foo
расширяется доdo this; do that; time foo
.Вы можете использовать это, чтобы создать магические псевдонимы, которые даже обходят цитирование.
Для вставки кода после команды вы можете использовать ловушку «DEBUG».
В частности:
Хук все еще запускается перед командой, но когда она возвращается,
false
он говорит bash отменить выполнение (потому что хук уже выполнил ее через eval).В качестве другого примера, вы можете использовать это псевдоним
command please
дляsudo command
:источник
Единственное решение, которое я мог бы найти до сих пор, - это выполнить анализ случая, чтобы определить, является ли первый аргумент командой, встроенным или ключевым словом, и в последнем случае произойдет сбой:
Однако он не обрабатывает
time
, так что может быть лучшее (и более краткое) решение.источник