Estoy tratando de crear un script bash que guardará el historial del terminal en un archivo llamado hist.txt. El uso history > hist.txtno parece funcionar en el script bash, pero funciona bien cuando se ejecuta en la línea de comando.
Cualquier orientación es muy apreciada.
Gracias Judy

~/.bash_historyarchivo del usuario .Respuestas:
Respuesta corta
Ejecute el script con
sourceo.:o
Este último es ligeramente más compatible en diferentes conchas.
Respuesta larga
Esta pregunta destaca un punto importante, que es que los scripts de shell se ejecutan en su propio contexto. Para ver lo que esto significa, considere el siguiente script de shell:
Si ejecuta esto, obtendrá un resultado similar a este:
Pero notará que después de ejecutar el script, todavía está en el directorio en el que se encontraba antes de ejecutarlo: el
cd /interior del script no ha afectado realmente su sesión, solo afectó el contexto en el que se estaba ejecutando el script, que se crea para que se ejecute el script y se destruye una vez que vuelve.El
sourcecomando 'leerá y ejecutará comandos del argumento del nombre de archivo en el contexto actual del shell', por lo que cualquier comando comocdeste afectará su sesión actual. Sisourcetuviera que ejecutar el script anterior al pasarlo, encontraría que termina dentro del directorio raíz después de que se ejecutó.En este caso, el problema es que el
historycomando le proporciona el historial del contexto actual del shell; el contexto de shell en el que se ejecuta su script sin usarsourceno tiene historial, por lo que no escribe nada en el archivo de salida. Si lo usasource, se ejecutará en el contexto correcto y funcionará como se espera.NB:
sourcees un shell integrado, no un programa en sí mismo ; en Bash,sourcees sinónimo de., pero en algunos shells solo.funcionará. Lo he usadosourceen esta respuesta porque es más fácil de leer que., pero para una compatibilidad máxima,.debería ser usado.fuente
En primer lugar, tenga en cuenta que su historial ya está en un archivo. Si está ejecutando bash, su nombre suele ser
~/.bash_history. Más específicamente, es lo que sea que haya configurado la variableHISTFILE. Si desea copiarlo a otro archivo, simplemente ejecutecat "$HISTFILE" > hist.txtAhora, por qué el
historycomando no funciona en un script de shell bash, es porque los scripts se ejecutan en un shell hijo no interactivo de su sesión de shell actual. Los shells secundarios no heredan todo el entorno del padre (por lo tanto, no todas las variables establecidas), solo las variables que se han exportado. Para ilustrar, el siguiente script hará eco del valor de la variable$var:Ahora, establece
$varalgo y ejecuta el script:A continuación, exporte la variable primero:
Como puede ver, cuando la variable se ha exportado, está disponible para shells secundarios.
Como mencioné antes, el historial se almacena en el archivo señalado por la variable
$HISTFILENAME. Como eso no se exporta de forma predeterminada, no se establece cuando se ejecuta un script:Como puede ver en el ejemplo anterior, la variable
HISTFILEse establece en mi sesión de shell normal, pero está vacía cuando se ejecuta el script.Entonces, para obtener el historial, tiene algunas opciones:
El valor predeterminado
HISTFILEvalor es$HOME/.bash_history. Si no ha cambiado eso, simplemente puede ejecutar este comando en su script:Puede pasar la
$HISTFILEvariable a su script ycateso:Guarde lo anterior como
foo.shy ejecute así:Asegúrese de que la variable se exporte. Agregue esta línea a sus archivos
~/.bash_profile(si existe) o~/.profile(si~/.bash_profileno existe):Luego, cierre la sesión y vuelva a iniciarla y debería poder ejecutar
history > hist.txtdesde un script como se esperaba. Esto se debe a queexport VARsignifica "poner $ VAR a disposición de los shells secundarios". En términos prácticos, esto significa que el valor deHISTFILEserá heredado por el shell no interactivo que utiliza para ejecutar su script.Ahora, aunque
HISTFILEse establecerá, el shell no lo ha leído al ejecutar el script. Entonces, para que funcione,history -rprimero debes leerlo . El guión completo se vería así:Alternativamente, simplemente expórtelo manualmente antes de ejecutar el script:
Pero aún lo necesitarás
history -ren el guión.Puede
sourcehacerlo como lo sugiere la respuesta de @ p0llard .fuente