Как я могу увидеть, какая команда была на самом деле запущена в оболочке, через псевдоним или функцию

20

Например, у меня есть функция bash (или псевдоним) function install() {sudo apt-get install $@}. При запуске команды install dicelab, я ожидаю, что на самом деле будет выполняться sudo apt-get install dicelab. Где я могу увидеть, что на самом деле было запущено оболочкой? Я хотел бы убедиться, что мои более сложные псевдонимы работают, как ожидалось.

Алон Авив
источник
Это $@часть вашего псевдонима? Помните, что псевдонимы на самом деле не поддерживают аргументы, которые распространяются на позиционные параметры (если они есть) контекста, вызывающего псевдоним. Обычный способ запуска somealias some argsработает, просто расширяя псевдоним и оставляя аргументы для него. Если вы действительно хотите получить доступ к аргументам, используйте функцию и процитируйте"$@"
ilkkachu
1
@AlonAviv, хорошо. :) Тем не менее, лучше всего взять в привычку цитировать, что "$@"аргументы с пробелами или глобальными символами будут гореть в противном случае.
ilkkachu
1
@DarkHeart Это не дубликат. Другой вопрос не касается функций оболочки.
Кусалананда
2
Ни один не был этим, пока это не было отредактировано, чтобы полностью изменить его предмет (и лишить законной силы один из существующих ответов).
Майкл Гомер

Ответы:

29

Используйте set -xв оболочке.

$ alias hello='echo hello world!'
$ hello
hello world!

$ set -x
$ hello
+ echo hello world!
hello world!

Использование set -xочереди на xtraceопции оболочки ( set +xвыключает) и должны работать во всех Bourne-подобных оболочек, как bash, dash ksh93, pdkshи zsh. Это заставляет оболочку отображать команду, которая выполняется после выполнения расширений псевдонимов, расширений переменных и т. Д.

Вывод будет происходить в стандартном потоке ошибок оболочки (так же, как в обычном приглашении), поэтому он не будет мешать перенаправлениям стандартного вывода, и ему будет предшествовать приглашение, определенное PS4переменной оболочки ( +␣по умолчанию).

Пример с несколькими функциями:

$ world () { echo "world"; }
$ hello () { echo "hello"; }
$ helloworld () { printf '%s %s!\n' "$(hello)" "$(world)"; }

$ helloworld
hello world!

$ set -x
$ helloworld
+ helloworld
++ hello
++ echo hello
++ world
++ echo world
+ printf '%s %s!\n' hello world
hello world!

Я использую set -xвсе мои интерактивные оболочки по умолчанию. Приятно видеть, что на самом деле было выполнено ... но я заметил, что программируемое завершение табуляции и т. Д. Может привести к нежелательному выводу трассы в некоторых оболочках.

Кусалананда
источник
14

Вы можете использовать shell-expand-line, что связано с Control- Alt- eпо умолчанию:

$ bind -p | grep shell-expand-line
"\e\C-e": shell-expand-line

Среди прочего, он заменит псевдонимы в текущей строке их определением, чтобы вы могли видеть команду, которую вы все еще собираетесь выполнить. Пример:

$ install dicelab # now press C-Alt-e
$ sudo apt-get install  dicelab # the above line will be replaced with this
Аркадиуш Драбчик
источник
это хорошая особенность. Знаете ли вы, если zsh имеет эквивалентную команду shell-expand-line?
the_velour_fog
Извините, но не пользуюсь zsh. Но некоторые люди придумали свои собственные идеи: wiki.math.cmu.edu/iki/wiki/tips/20140625-zsh-expand-alias.html
Аркадиуш Драбчик
1

Вы можете использовать встроенную bash type, чтобы увидеть псевдоним или определение функции, которую вы собираетесь запустить:

$ type ls
ls is aliased to `ls --color=auto -p'

$ type -a ls
ls is aliased to `ls --color=auto -p'
ls is /bin/ls

$ install() { sudo apt-get install "@"; }

$ type install
install is a function
install () 
{ 
    aptitude install "@"
}
belkka
источник