Використовуйте системну команду замість вбудованого Bash, не вказуючи повний шлях


17

Я використовую Bash як свою інтерактивну оболонку, і мені було цікаво, чи існує простий спосіб змусити Bash запустити системну команду замість вбудованої команди оболонки у випадку, коли вони обидва мають одне й те саме ім'я.

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

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

Не вказуючи повний шлях системної команди, замість системної команди використовується вбудований Bash. killВбудований не має -pопції , щоб команда не:

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

Я спробував відповіді, наведені в Make make bash, використовувати зовнішню команду `time`, а не вбудовану оболонку, але більшість з них працює лише тому, що timeце фактично ключове слово shell, а не вбудована оболонка .

Окрім тимчасового відключення вбудованого Bash enable -n kill, найкращим рішенням, яке я бачив до цього часу, є використання:

$(which kill) -p httpd

Чи існують інші простіші способи (які передбачають менший набір тексту) для виконання зовнішньої команди замість вбудованої оболонки?

Зауважте, що killце лише приклад, і мені хотілося б узагальненого рішення, подібного до того, як префіксація commandвбудованого файлу запобігає виконанню функцій, що мають те саме ім'я, що і зовнішня команда. У більшості випадків я зазвичай вважаю за краще використовувати вбудовану версію, оскільки це економить розгортання нового процесу, а іноді вбудований має функції, яких не має зовнішня команда.


Замикання which killв задній частині (не можна помістити їх у коментарі) трохи коротше.
abligh

@abligh Добре. Я витратив роки на навчання, щоб використовувати "новий" синтаксис ер для заміни команд. :)
Ентоні Г - справедливість для Моніки

@abligh: FYI, ви можете розміщувати `зворотні посилання 'в коментарях, попередньо додаючи їх в косому куті (\). Але є причини дотримуватися $(…)- дивіться це , це і це .
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будь-якої іншої програми , як це.
користувач253751

1

Найпростіший спосіб зробити те, що ви хочете, - це поставити лінію

alias kill="/bin/kill"

у ваш ~/.bashrcфайл. Після цього кожен новий вхід / виклик bash буде інтерпретувати "убивати" як /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

Але якщо вам потрібно менше вводити текст, немає кращого способу, ніж хороший псевдонім.

З поняття "список pid" (lp):

alias lp='/bin/kill -p'

тоді просто введіть:

lp httpd

0

(З zsh) Ви можете встановити префікс будь-якого імені команди зі знаком =, щоб отримати системну версію замість вбудованої. Це також зручний спосіб ухилитися від псевдонімів, які псують конкретний сценарій.

$ =kill -p httpd

1
Я спробував це з версією Bash 4.3.30, і це не вийшло. Я ніколи раніше не бачив такого синтаксису; чи можете ви додати посилання на те, де ця функція задокументована? Як правило, ви можете встановити псевдонім із зворотною косою рисою, щоб запустити непредмещену версію команди.
Ентоні Г - справедливість для Моніки

@Anthony, можливо, це 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.