Используйте системную команду вместо встроенной Bash без указания полного пути


17

Я использую Bash в качестве интерактивной оболочки, и мне было интересно, есть ли простой способ заставить Bash выполнить системную команду вместо встроенной команды оболочки, если они оба имеют одно и то же имя.

Например, используйте system kill(from util-linux) для печати идентификатора процесса (pid) указанного процесса (ов) вместо отправки сигнала:

$ /bin/kill -p httpd
2617
...

Без указания полного пути к системной команде вместо системной команды используется встроенная команда Bash. killВстроенный не имеет -pопции , чтобы команда не:

$ kill -p httpd
bash: kill: p: invalid signal specification

Я попробовал ответы, перечисленные в Make bash, используя внешнюю команду `time` вместо встроенной оболочки, но большинство из них работают только потому, что timeна самом деле это ключевое слово shell, а не встроенная оболочка .

Помимо временного отключения встроенной функции Bash enable -n kill, лучшим решением, которое я видел до сих пор, является использование:

$(which kill) -p httpd

Существуют ли другие более простые (требующие меньшего количества ввода) способы выполнения внешней команды вместо встроенной оболочки?

Обратите внимание, что killэто всего лишь пример, и я хотел бы получить обобщенное решение, подобное тому, как префикс с помощью commandвстроенной функции предотвращает запуск функций, имеющих то же имя, что и у внешней команды. В большинстве случаев я обычно предпочитаю использовать встроенную версию, так как она сохраняет ветвление нового процесса, и иногда встроенная функция имеет функции, которых нет у внешней команды.


Заключение which killв кавычки (не могу поместить их в комментарии) немного короче.
abligh

@abligh Хорошая мысль. Я потратил годы, тренируясь, чтобы использовать «новый» синтаксис er для подстановки команд. :)
Энтони Дж. - справедливость для Моники

@abligh: К вашему сведению, вы можете добавить в комментарии `backticks`, поставив перед ними обратную косую черту (\). Но есть причины придерживаться этого $(…)- увидеть это , это и это .
G-Man говорит: «Восстанови Монику»

Ответы:


20

Предположим env, на вашем пути:

env kill -p http

envзапускает исполняемый файл с именем по первому аргументу в (возможно) измененной среде; как таковой, он не знает или не работает со встроенными командами оболочки.

Это приводит к некоторому сбою управления заданиями оболочки, но не зависит от внешней команды:

exec kill -p bash &

execтребует замены исполняемого файла для текущей оболочки, поэтому не использует никаких встроенных модулей. Задание выполняется в фоновом режиме, поэтому вы заменяете разветвленную фоновую оболочку, а не текущую.


2
envэто явно правильный ответ ИМХО.
abligh

@abligh: Вы правы в комментарии в моем удаленном ответе. command -p cmdвызывая внешнюю команду zsh, нет bash.
cuonglm

6
(exec kill -p http)заставляет задание заменять вложенную оболочку вместо вашей текущей оболочки, и вам не нужно иметь дело с обработкой управления заданиями.
Майкл Хоффман

1
@AnthonyGeoghegan Действительно, но envтакже не знает о встроенных функциях оболочки, так как это не оболочка. Вы бы получить тот же эффект с niceили xargsили любой другой программой , как это.
user253751

1

Самый простой способ сделать то, что вы хотите, это поставить строку

alias kill="/bin/kill"

в ваш ~/.bashrcфайл. После этого каждый новый логин / вызов bash будет интерпретироваться как kill /bin/kill.


Я уже думал о псевдониме, и это было одно из решений, перечисленных в вопросе, с которым я связан, но я надеюсь на более обобщенное решение (аналогичное commandрешению), а не на создание отдельного псевдонима для каждой «скрытой» команды. Теперь я отредактировал свой вопрос, чтобы сделать его более понятным и понятным. В большинстве случаев я обычно предпочитаю использовать встроенную версию, поскольку процессы могут быть определены идентификаторами заданий. Спасибо, в любом случае.
Энтони Дж - справедливость для Моники

1

Если вы знаете решение, которое требует некоторой типизации, и вы хотите решение, которое требует меньше набора, создайте его:

runFile() { local cmd="$1"; shift; cmd="$(which "$cmd")" && "$cmd" "$@"; }

Аббревиатура, которая обычно требует определенных усилий, - это то, в чем превосходят компьютеры.


1
Это хороший общий момент, поэтому я буду приветствовать ваш ответ. За последние несколько лет я собрал коллекцию псевдонимов, функций и сценариев для систем, которые я регулярно использую. Однако я предпочитаю использовать нестандартные решения, где это возможно, поскольку мне иногда приходится работать на новых установках или серверах, которые я не настраивал. Благодарю.
Энтони Дж - правосудие для Моники

1

В этом очень конкретном случае команда pgrepявляется точным соответствием необходимости.

В общем смысле функция работает. Из «файловой команды»:

fcmd(){ local a=$1; shift; $(which "$a") "$@"; }

называть как

fcmd kill -p httpd

Но если вам нужно меньше печатать, нет более короткого пути, чем хороший псевдоним.

Из понятия «список пидов» (lp):

alias lp='/bin/kill -p'

затем просто введите:

lp httpd

0

(В zsh) Вы можете добавить к имени любой команды знак =, чтобы получить системную версию вместо встроенной. Это также удобный способ уклониться от любых псевдонимов, которые портят определенный сценарий.

$ =kill -p httpd

1
Я попробовал это с версией Bash 4.3.30, и она не работала. Я никогда не видел такой синтаксис раньше; Вы можете добавить ссылку, где эта функция задокументирована? Обычно я запускаю псевдоним с обратной косой чертой для запуска не псевдонимной версии команды.
Энтони Дж - справедливость для Моники

@ Энтони, возможно, это zshединственное. Я пользуюсь им регулярно, но bashзавтра проверю с компьютера.
Калеб

Я подозревал, что это может быть какая-то оболочка, с которой я не знаком (я только знаком с bash, dash и csh). Был другой ответ (так как удален), который работал только для zsh. Хотя я пометил этот вопрос bashи использовал его в заголовке, вы должны сохранить этот ответ, так как пользователь zsh все равно сочтет его полезным.
Энтони Дж - справедливость для Моники

-1

Вы можете отправить отчет об ошибке на вашу страницу killруководства и спросить, почему это включает в себя нестандартные опции, которые взяты изpkill и используются в pkillлюбое время, когда вы хотите получить функции отpkill.

Если вы позвоните:

pkill httpd

Вы избегаете проблем, которые вы описываете.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.