Devo scrivere uno script che scriva su un file quante volte questo script è stato eseguito.
Come posso fare ciò?
Devo scrivere uno script che scriva su un file quante volte questo script è stato eseguito.
Come posso fare ciò?
Risposte:
Presumo che tu voglia avere un singolo file countfile
che contiene solo un singolo numero che rappresenta il contatore dell'esecuzione.
Puoi leggere questo contatore in una variabile di shell, $counter
ad esempio usando una di queste righe:
read counter < countfile
counter=$(cat countfile)
È possibile eseguire semplici aggiunte di numeri interi in Bash utilizzando la $(( EXPRESSION ))
sintassi. Quindi riscrivi semplicemente il risultato nel nostro countfile
:
echo "$(( counter + 1 ))" > countfile
Probabilmente dovresti anche salvaguardare il tuo script per il caso che countfile
non esiste ancora e crearne uno inizializzato con il valore 1 quindi.
L'intera cosa potrebbe apparire così:
#!/bin/bash
if [[ -f countfile ]] ; then
read counter < countfile
else
counter=0
fi
echo "$(( counter + 1 ))" > countfile
$(…)
venga eseguito prima di ogni altra cosa (specialmente prima del >
). Ma uso spesso la $(cat countfile 2>/dev/null || echo 0)
parte per ottenere un valore predefinito ragionevole nel caso in cui il file non esista. Potremmo aggiungere un sponge
:-) per essere al sicuro.
flock
comando per prevenire le condizioni di gara. Vedi unix.stackexchange.com/a/409276
Lascia che lo script crei un file di registro, aggiungi ad esempio una riga nello script alla fine:
echo "Script has been executed at $(date +\%Y-\%m-\%d) $(date +\%H-\%M-\%S)" >> ~/script.log
In questo modo puoi formattare tu stesso il modo in cui presenti la data e l'ora, ma se vuoi semplicemente andare con una data e un'ora complete (ed HH:MM:SS
è un formato accettabile per te) puoi anche semplicemente usare:
echo "Script has been executed at $(date +\%F-\%T)" >> ~/script.log
Quindi potresti fare:
wc -l ~/script.log
Che conta i caratteri di nuova riga e ti dà una stima di quante righe ci sono nel file di registro. Fino a questo puoi vedere nel file di registro anche quando è stato eseguito. Per adattarlo alle proprie esigenze, è possibile modificare i percorsi e i nomi utilizzati per la registrazione. Ho appena fatto un esempio qui che salva il file di log ~
.
Quindi, ad esempio, se vuoi che lo script aggiunga questo conteggio alla riga che hai aggiunto alla fine dello script, potresti fare qualcosa del genere all'inizio dello 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"
E cambia la tua linea alla fine dello script in qualcosa che includa anche quelle informazioni:
echo "Script has been executed $count times at $(date +\%F-\%T)" >> ~/script.log
Questa soluzione utilizza lo stesso approccio della risposta di Byte Commander ma non si basa sull'aritmetica della shell o su altri Bashismi.
exec 2>&3 2>/dev/null
read counter < counter.txt || counter=0
exec 3>&2 3>&-
expr "$counter" + 1 > counter.txt
I reindirizzamenti dello stream
/dev/null
(per sopprimere il messaggio di errore nel successivo reindirizzamento dell'input del read
comando se il file del contatore manca in modo previsto),Un file contatore separato presenta degli svantaggi:
Quindi questa risposta elimina un file contatore separato e inserisce il conteggio nello stesso script bash!
flock
garantisce che per un breve momento non è possibile per due utenti eseguire lo script contemporaneamente.#!/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
Simile alla risposta di Videonauth, ho scritto una risposta per il file di registro qui: script Bash per mantenere la traccia di controllo / registro dei file a cui si accede ogni volta che si usano i poteri di root con gedit
o nautilus
.
Il problema è che piuttosto che usare gksu
lo script è chiamato gsu
e invoca pkexec
il modo "moderno" di usare sudo nella GUI, così mi viene detto.
Un altro vantaggio non è solo dire ogni volta che sono stati utilizzati i poteri di root, gedit
ma registra il nome del file che è stato modificato. Ecco il codice
~/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
Contenuto del file di registro gsu-log-file-for-gedit
dopo alcune modifiche:
__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