Cómo forzar a watch a correr bajo bash

18

El problema es que cuando se ejecuta watch se ejecuta shy aparece este error:

sh: 1: func1: not found

Aquí está el código:

#!/bin/bash

func1(){
  echo $1
}

export -f func1

watch func1
Rachid Oussanaa
fuente
¿Puedes darme el comando que realmente ejecutas?
Cuonglm
@Gnouc en lugar de echo $ 1, tengo un script un poco largo, así que no sé ...
Rachid Oussanaa
Quiero decir, ¿cómo ejecutaste tu comando ssh?
Cuonglm
@Gnouc ./bin/myfunc.sh
Rachid Oussanaa

Respuestas:

10

Ok, hay algunos problemas con su enfoque.

Está exportando una función que no es portátil entre shells. watchejecuta sus comandos con /bin/sh, que en su sistema no lo es bash. Y sea cual sea el shell, no respeta las exportaciones de funciones, por lo que obtiene el error.

En segundo lugar, puede cambiar su comando a algo así watch bash -c 'func1', pero esto puede no funcionar bien tampoco.
La razón aquí es que las variables establecidas por el script no estarán disponibles para la función. Es posible que pueda exportar los que necesita, pero eso comienza a complicarse.

La solución más segura es poner func1un script por sí mismo y llamarlo.
 

En resumen, intente:

watch bash -c func1
Patricio
fuente
1
Es muy intensivo en CPU en caso de que la función se defina en.bash_profile
VarunAgw
@VarunAgw, ese es un buen punto. Sin embargo, es un gran comando para monitorear cosas en un entorno donde el .bash_profilearchivo está relativamente vacío. Sin embargo, quería ejecutar un alias que estaba en mi .bash_aliasesarchivo ( obtenido a través de mi.bashrc ), así que terminé agregando la -ibandera a bash también. Pensé que eso podría ayudar a alguien:watch bash -ic "func1; alias1; func2; …"
aaiezza
Solo watch -x bash -c my-funcfunciona para mí en Ubuntu Server 16.04, mientras que otros no.
Nam G VU
14

El shell predeterminado para watches /bin/sh. Los shells no heredarán variables o funciones exportadas de otros tipos de shell.

Si el sistema no enlace simbólico /bin/sha /bin/bash(o su shell actual), entonces usted puede instruir watcha exec su shell mediante el uso de -xo --exec:

watch -x bash -c "my_func"

o

watch --exec bash -c "my_func"

Esto es diferente a watch bash -c "test_watch"(excluyendo el --exec) ya que no se usa /bin/shpara generar el proceso hijo (en este caso bash), manteniendo bashtodo el camino hacia abajo. Como se dice en otras respuestas, esto puede ser complicado si se exportan funciones que están altamente acopladas al entorno actual (es decir, que requieren otras variables o funciones).


Un ejemplo:

test_watch() { echo 'Working!'; }
export -f test_watch
watch --exec bash -c "test_watch"

da lo familiar

Every 2.0s: bash -c test_watch                                   Thu Mar 31 11:15:56 2016

Working!
Andy
fuente
Solo que watch -x bash -c my-funcsí, esto funciona para mí en Ubuntu Server 16.04, mientras que otros no. ¡Gracias una tonelada!
Nam G VU
4

¿Por qué correr watchdesde dentro de tu script? ¿Por qué no tener este script de shell?

$ cat func1 
#!/bin/bash

func1(){
  echo $1
}

func1 $1

... y luego ejecutarlo así ...

$ watch func1 foo
Grillo rojo
fuente