Utilizzare il comando di sistema anziché Bash incorporato senza specificare il percorso completo


17

Uso Bash come shell interattiva e mi chiedevo se esistesse un modo semplice per far eseguire a Bash un comando di sistema invece di un comando incorporato della shell nel caso in cui entrambi condividessero lo stesso nome.

Ad esempio, utilizzare il sistema kill(da util-linux) per stampare l'ID di processo (pid) dei processi denominati anziché inviare un segnale:

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

Senza specificare il percorso completo del comando di sistema, al posto del comando di sistema viene utilizzato l'integrato di Bash. Il killbuiltin non ha l' -popzione quindi il comando fallisce:

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

Ho provato le risposte elencate in Fa in modo che bash usi il comando `time` esterno piuttosto che la shell integrata, ma la maggior parte di esse funziona solo perché in timerealtà è una parola chiave della shell , non una shell incorporata .

Oltre a disabilitare temporaneamente Bash integrato con enable -n kill, la migliore soluzione che ho visto finora è usare:

$(which kill) -p httpd

Esistono altri modi più semplici (implicano meno battitura) di eseguire un comando esterno invece di un comando incorporato della shell?

Si noti che killè solo un esempio e vorrei una soluzione generalizzata simile al modo in cui il prefisso con l' commandintegrato impedisce l'esecuzione di funzioni con lo stesso nome di un comando esterno. Nella maggior parte dei casi, di solito preferisco usare la versione integrata in quanto consente di salvare il fork di un nuovo processo e alcune volte l'integrato ha funzionalità che il comando esterno non ha.


Racchiudere which killin backtick (non è possibile inserirlo nei commenti) è leggermente più breve.
circa

@abligh Ottimo punto. Ho passato anni ad allenarmi per usare la "nuova" sintassi per la sostituzione del comando. :)
Anthony G - giustizia per Monica,

@abligh: Cordiali saluti, puoi inserire `backtick` nei commenti precedendoli con le barre rovesciate (\). Ma ci sono ragioni per restare fedeli $(…): vedi questo , questo e questo .
G-Man dice "Reinstate Monica" il

Risposte:


20

Supponendo che envsia nel tuo percorso:

env kill -p http

envesegue il file eseguibile chiamato dal suo primo argomento in un ambiente (possibilmente) modificato; come tale, non conosce o non funziona con i comandi integrati della shell.

Questo produce un certo controllo del processo di shell ma non si basa su un comando esterno:

exec kill -p bash &

execrichiede un eseguibile per sostituire la shell corrente, quindi non usa alcun built-in. Il lavoro viene eseguito in background in modo da sostituire la shell di sfondo biforcuta, non la shell corrente.


2
envè chiaramente la risposta giusta IMHO.
circa

@abligh: hai ragione nel commento nella mia risposta eliminata. command -p cmdchiamando il comando esterno zsh, no bash.
cuonglm,

6
(exec kill -p http)fa sì che il lavoro sostituisca una sotto-shell invece della tua shell corrente e non devi occuparti della cruft di controllo del lavoro.
Michael Hoffman,

1
@AnthonyGeoghegan In effetti, ma envnon conosce i builtin della shell, dal momento che non è una shell. Otterresti lo stesso effetto con niceo con xargsqualsiasi altro programma del genere.
user253751

1

Il modo più semplice per fare ciò che vuoi potrebbe essere quello di mettere la linea

alias kill="/bin/kill"

nel tuo ~/.bashrcfile. Successivamente, ogni nuovo login / invocazione di bash interpreterà "kill" come /bin/kill.


Avevo già pensato a un alias e quella era una delle soluzioni elencate nella domanda a cui mi collegavo, ma spero in una soluzione più generalizzata (simile alla commandsoluzione) piuttosto che creare un alias separato per ogni comando "ombreggiato". Ora ho modificato la mia domanda per renderlo più chiaro ed esplicito. Nella maggior parte dei casi, di solito preferisco utilizzare la versione integrata poiché i processi possono essere specificati dagli ID lavoro. Grazie comunque.
Anthony G - giustizia per Monica,

1

Se conosci una soluzione che richiede una certa digitazione e desideri una soluzione che richieda meno digitazione, creala:

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

L'abbreviazione che normalmente richiede un certo sforzo è ciò in cui eccellono i computer.


1
Questo è un buon punto generale, quindi voterò la tua risposta. Negli ultimi anni, ho creato una raccolta di alias, funzioni e script per i sistemi che uso regolarmente. Tuttavia, preferisco utilizzare soluzioni non personalizzate, ove possibile, poiché a volte devo lavorare su nuove installazioni o server che non ho impostato. Grazie.
Anthony G - giustizia per Monica,

1

In questo caso molto specifico, il comando pgrepcorrisponde esattamente all'esigenza.

In senso generale, una funzione funziona. Da "comando file":

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

chiama come

fcmd kill -p httpd

Ma se hai bisogno di meno digitazioni, non c'è modo più breve di un buon alias.

Dal concetto "list pid" (lp):

alias lp='/bin/kill -p'

quindi, basta digitare:

lp httpd

0

(In zsh) È possibile aggiungere un prefisso a qualsiasi nome di comando con un segno = per ottenere la versione del sistema anziché un predefinito. Questo è anche un modo pratico per schivare eventuali alias che incasinano uno scenario specifico.

$ =kill -p httpd

1
L'ho provato con la versione 4.3.30 di Bash e non ha funzionato. Non ho mai visto una sintassi simile prima d'ora; puoi aggiungere un link dove è documentata questa funzione? Normalmente aggiungerei un alias con una barra rovesciata per eseguire la versione non alias di un comando.
Anthony G - giustizia per Monica,

@Anthony forse questa è l' zshunica cosa. Lo uso regolarmente ma bashdomani controllerò da un computer.
Caleb,

Sospettavo che potesse trattarsi di una shell con cui non ho familiarità (ho familiarità solo con bash, dash e csh). C'è stata un'altra risposta (da quando è stata eliminata) per cui ha funzionato zsh. Mentre ho taggato questa domanda con bashe l'ho usata nel titolo, dovresti mantenere questa risposta poiché un utente zsh la troverebbe comunque utile.
Anthony G - giustizia per Monica,

-1

È possibile inviare un bug report sulla propria killpagina man e chiedere perché ciò include opzioni non standard che vengono prese pkille utilizzate pkillogni volta che si desidera ottenere le funzionalità dapkill.

Se chiami:

pkill httpd

eviti i problemi che descrivi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.