Use el comando del sistema en lugar de Bash incorporado sin especificar la ruta completa

17

Utilizo Bash como mi shell interactivo y me preguntaba si había una manera fácil de hacer que Bash ejecutara un comando del sistema en lugar de un comando incorporado del shell en el caso en que ambos compartan el mismo nombre.

Por ejemplo, use el sistema kill(desde util-linux) para imprimir la identificación del proceso (pid) de los procesos nombrados en lugar de enviar una señal:

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

Sin especificar la ruta completa del comando del sistema, se utiliza el Bash incorporado en lugar del comando del sistema. El killincorporado no tiene la -popción, por lo que el comando falla:

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

Intenté las respuestas enumeradas en Hacer que bash use el comando externo `time` en lugar del shell incorporado, pero la mayoría de ellas solo funcionan porque en timerealidad es una palabra clave de shell , no un shell incorporado. .

Además de deshabilitar temporalmente el Bash incorporado enable -n kill, la mejor solución que he visto hasta ahora es usar:

$(which kill) -p httpd

¿Hay otras formas más fáciles (implican menos escribir) de ejecutar un comando externo en lugar de un shell incorporado?

Tenga en cuenta que killes solo un ejemplo y me gustaría una solución generalizada similar a la forma en que el prefijo con el commandincorporado evita que se ejecuten funciones que tienen el mismo nombre que un comando externo. En la mayoría de los casos, generalmente prefiero usar la versión incorporada, ya que ahorra bifurcar un nuevo proceso y algunas veces la función incorporada tiene características que el comando externo no tiene.

Anthony G - justicia para Monica
fuente
El encerrar which killen backticks (no puedo ponerlos en los comentarios) es un poco más corto.
Abligh
@abligh Buen punto. He pasado años entrenándome para usar la "nueva" sintaxis er para la sustitución de comandos. :)
Anthony G - justicia para Monica
@abligh: FYI, puedes poner 'backticks' en los comentarios precediéndolos con barras invertidas (\). Pero hay razones para seguir $(…): vea esto , esto y esto .
G-Man dice 'reinstalar a Mónica' el

Respuestas:

20

Asumiendo que envestá en tu camino:

env kill -p http

envejecuta el archivo ejecutable nombrado por su primer argumento en un (posiblemente) entorno modificado; como tal, no conoce ni funciona con los comandos integrados de shell.

Esto produce un poco de control de trabajo de shell, pero no se basa en un comando externo:

exec kill -p bash &

execrequiere un ejecutable para reemplazar el shell actual, por lo que no utiliza ningún elemento integrado. El trabajo se ejecuta en segundo plano para que reemplace el shell de fondo bifurcado, no su shell actual.

chepner
fuente
2
enves claramente la respuesta correcta en mi humilde opinión.
abligh
@abligh: Tienes razón en el comentario en mi respuesta eliminada. command -p cmdinvocando comando externo zsh, no bash.
Cuonglm
66
(exec kill -p http)hace que el trabajo reemplace un sub-shell en lugar de su shell actual y no tiene que lidiar con el control de trabajo cruft.
Michael Hoffman el
1
@AnthonyGeoghegan De hecho, pero envtampoco sabe acerca de la construcción de conchas, ya que no es una concha. Obtendría el mismo efecto con niceo con xargscualquier otro programa como ese.
user253751
1

La forma más simple de hacer lo que quieres podría ser poner la línea

alias kill="/bin/kill"

en tu ~/.bashrcarchivo. Después de eso, cada nuevo inicio de sesión / invocación de bash interpretará "kill" como /bin/kill.

Benjamin Staton
fuente
Ya había pensado en un alias y esa era una de las soluciones enumeradas en la pregunta a la que me vinculé, pero espero una solución más generalizada (similar a la commandsolución) en lugar de crear un alias separado para cada comando "sombreado". Ahora he editado mi pregunta para hacer esto más claro y más explícito. En la mayoría de los casos, generalmente prefiero usar la versión integrada, ya que los procesos pueden especificarse mediante ID de trabajo. Gracias de cualquier manera.
Anthony G - justicia para Monica
1

Si conoce una solución que requiere algo de escritura y desea una solución que requiera menos escritura, compílela:

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

Abreviar cosas que normalmente requieren cierto esfuerzo es en lo que se destacan las computadoras.

PSkocik
fuente
1
Ese es un buen punto general, así que votaré su respuesta. En los últimos años, he creado una colección de alias, funciones y scripts para los sistemas que uso regularmente. Sin embargo, prefiero usar soluciones no personalizadas siempre que sea posible, ya que a veces tengo que trabajar en nuevas instalaciones o servidores que no configuré. Gracias.
Anthony G - justicia para Monica
1

En este caso muy específico, el comando pgrep es una coincidencia exacta para la necesidad.

En un sentido general, una función funciona. Desde "comando de archivo":

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

llamar como

fcmd kill -p httpd

Pero si necesita escribir menos, no hay forma más corta que un buen alias.

Del concepto "list pid" (lp):

alias lp='/bin/kill -p'

entonces, simplemente escriba:

lp httpd

fuente
0

(En zsh) Puede prefijar cualquier nombre de comando con un signo = para obtener la versión del sistema en lugar de una incorporada. Esta también es una forma práctica de esquivar cualquier alias que arruine un escenario específico.

$ =kill -p httpd
Caleb
fuente
1
Intenté eso con Bash versión 4.3.30 y no funcionó. Nunca he visto tal sintaxis antes; ¿Puedes agregar un enlace a donde esta función está documentada? Normalmente prefijo un alias con una barra diagonal inversa para ejecutar la versión sin alias de un comando.
Anthony G - justicia para Monica
@ Anthony tal vez esto es una zshcosa única. Lo uso regularmente, pero lo revisaré bashdesde una computadora mañana.
Caleb
Sospeché que podría ser algún shell con el que no estoy familiarizado (solo estoy familiarizado con bash, dash y csh). Hubo otra respuesta (ya eliminada) que solo funcionó zsh. Si bien etiqueté esta pregunta bashy la usé en el título, debe mantener esta respuesta ya que un usuario de zsh aún la encontraría útil.
Anthony G - justicia para Monica
-1

Puede enviar un informe de error contra su página de killmanual y preguntar por qué esto incluye opciones no estándar que se toman pkilly usanpkill cada vez que desea obtener las funciones depkill.

Si llamas:

pkill httpd

evita los problemas que describe.

astuto
fuente