Necesito escribir un script que escriba en un archivo cuántas veces se ha ejecutado este script.
¿Cómo puedo hacer eso?
Necesito escribir un script que escriba en un archivo cuántas veces se ha ejecutado este script.
¿Cómo puedo hacer eso?
Respuestas:
Supongo que desea tener un solo archivo countfile
que solo contenga un único número que represente el contador de ejecución.
Puede leer este contador en una variable de shell, $counter
por ejemplo, usando una de estas líneas:
read counter < countfile
counter=$(cat countfile)
Las adiciones enteras simples se pueden hacer en Bash usando la $(( EXPRESSION ))
sintaxis. Luego simplemente escriba el resultado en nuestro countfile
:
echo "$(( counter + 1 ))" > countfile
Probablemente también debería proteger su script para el caso que countfile
aún no existe y crear uno inicializado con el valor 1 en ese momento.
Todo podría verse así:
#!/bin/bash
if [[ -f countfile ]] ; then
read counter < countfile
else
counter=0
fi
echo "$(( counter + 1 ))" > countfile
$(…)
se ejecute antes que nada (especialmente antes del >
). Pero a menudo uso la $(cat countfile 2>/dev/null || echo 0)
parte para obtener un valor predeterminado razonable en caso de que el archivo no exista. Podríamos agregar un sponge
:-) para estar seguro.
flock
comando para evitar condiciones de carrera. Ver unix.stackexchange.com/a/409276
Simplemente deje que el script cree un archivo de registro, agregue, por ejemplo, una línea en su script al final:
echo "Script has been executed at $(date +\%Y-\%m-\%d) $(date +\%H-\%M-\%S)" >> ~/script.log
De esta forma, puede formatear la fecha y la hora usted mismo, pero si simplemente desea ir con una fecha y hora completas (y HH:MM:SS
es un formato aceptable para usted), también puede simplemente usar:
echo "Script has been executed at $(date +\%F-\%T)" >> ~/script.log
Entonces podrías hacer:
wc -l ~/script.log
Que cuenta los caracteres de nueva línea y le da una estimación de cuántas líneas hay dentro del archivo de registro. Hasta eso puede ver dentro del archivo de registro incluso cuando se ejecutó. Para adaptarlo a sus necesidades, puede cambiar las rutas y los nombres utilizados para iniciar sesión. Acabo de hacer un ejemplo aquí que guarda el archivo de registro ~
.
Entonces, por ejemplo, si desea que el script agregue este conteo a la línea que agregó al final de su script, podría hacer algo como esto al comienzo de su script:
count=$(( $(wc -l ~/script.log | awk '{print $1}') + 1 ))
# the next line can be simply skipped if you not want an output to std_out
echo "Script execution number: $count"
Y cambie su línea al final del guión a algo que incluya incluso esa información:
echo "Script has been executed $count times at $(date +\%F-\%T)" >> ~/script.log
Esta solución utiliza el mismo enfoque que la respuesta de Byte Commander, pero no se basa en aritmética de shell u otros Bashismos.
exec 2>&3 2>/dev/null
read counter < counter.txt || counter=0
exec 3>&2 3>&-
expr "$counter" + 1 > counter.txt
Las redirecciones de flujo
/dev/null
(para suprimir el mensaje de error en la redirección posterior de la entrada del read
comando si el archivo del contador falta)Un archivo de contador separado tiene desventajas:
¡Entonces esta respuesta elimina un archivo de contador separado y coloca el conteo en el script bash mismo!
flock
garantiza que por un breve momento no es posible que dos usuarios ejecuten el script al mismo tiempo.#!/bin/bash
# NAME: run-count.sh
# PATH: $HOME/bin
# DESC: Written for AU Q&A: /ubuntu/988032/how-can-i-cause-a-script-to-log-in-a-separate-file-the-number-of-times-it-has-be
# DATE: Mar 16, 2018.
# This script run count: 0
# ======== FROM HERE DOWN CAN GO INTO FILE INCLUDED WITH SOURCE COMMAND =======
[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :
# This is useful boilerplate code for shell scripts. Put it at the top of
# the shell script you want to lock and it'll automatically lock itself on
# the first run. If the env var $FLOCKER is not set to the shell script
# that is being run, then execute flock and grab an exclusive non-blocking
# lock (using the script itself as the lock file) before re-execing itself
# with the right arguments. It also sets the FLOCKER env var to the right
# value so it doesn't run again.
# Read this script with entries separated newline " " into array
mapfile -t ScriptArr < "$0"
# Build search string that cannot be named
SearchStr="This script"
SearchStr=$SearchStr" run count: "
# Find our search string in array and increment count
for i in ${!ScriptArr[@]}; do
if [[ ${ScriptArr[i]} = *"$SearchStr"* ]]; then
OldCnt=$( echo ${ScriptArr[i]} | cut -d':' -f2 )
NewCnt=$(( $OldCnt + 1 ))
ScriptArr[i]=$SearchStr$NewCnt
break
fi
done
# Rewrite our script to disk with new run count
# BONUS: Date of script after writing will be last run time
printf "%s\n" "${ScriptArr[@]}" > "$0"
# ========= FROM HERE UP CAN GO INTO FILE INCLUDED WITH SOURCE COMMAND ========
# Now we return you to your original programming....
exit 0
Similar a la respuesta de Videonauth, escribí una respuesta de archivo de registro aquí: secuencia de comandos Bash para mantener el seguimiento / registro de auditoría de los archivos accedidos para registrar cada vez que se usaban poderes de raíz con gedit
o nautilus
.
Sin embargo, el problema es que en lugar de usar gksu
el script se nombra gsu
e invoca pkexec
la forma "moderna" de usar sudo en la GUI, por lo que me han dicho.
Otra ventaja es que no solo dice cada vez que se usaron poderes de raíz, gedit
sino que registra el nombre del archivo que se editó. Aquí está el código.
~/bin/gsu
:
#!/bin/bash
# Usage: gsu gedit file1 file2...
# -OR- gsu natuilus /dirname
# & is used to spawn process and get prompt back ASAP
# > /dev/null is used to send gtk warnings into dumpster
COMMAND="$1" # extract gedit or nautilus
pkexec "$COMMAND" "${@:2}"
log-file "${@:2}" gsu-log-file-for-"$COMMAND"
/usr/local/bin/log-file
:
#! /bin/bash
# NAME: log-file
# PATH: /usr/local/bin
# DESC: Update audit trail/log file with passed parameters.
# CALL: log-file FileName LogFileName
# DATE: Created Nov 18, 2016.
# NOTE: Primarily called from ~/bin/gsu
ABSOLUTE_NAME=$(realpath "$1")
TIME_STAMP=$(date +"%D - %T")
LOG_FILE="$2"
# Does log file need to be created?
if [ ! -f "$LOG_FILE" ]; then
touch "$LOG_FILE"
echo "__Date__ - __Time__ - ______File Name______" >> "$LOG_FILE"
# MM/DD/YY - hh:mm:ss - "a/b/c/FileName"
fi
echo "$TIME_STAMP" - '"'"$ABSOLUTE_NAME"'"' >> "$LOG_FILE"
exit 0
Contenido del archivo de registro gsu-log-file-for-gedit
después de algunas ediciones:
__Date__ - __Time__ - ______File Name______
11/18/16 - 19:07:54 - "/etc/default/grub"
11/18/16 - 19:08:34 - "/home/rick/bin/gsu"
11/18/16 - 19:09:26 - "/home/rick/bin/gsu"
echo $(( $(cat countfile 2>/dev/null || echo 0) + 1 )) > countfile