Preciso escrever um script que grave em um arquivo quantas vezes esse script foi executado.
Como eu posso fazer isso?
Preciso escrever um script que grave em um arquivo quantas vezes esse script foi executado.
Como eu posso fazer isso?
Respostas:
Suponho que você queira ter um único arquivo countfileque contenha apenas um número único representando o contador de execução.
Você pode ler este contador em uma variável shell, $counterpor exemplo, usando uma destas linhas:
read counter < countfilecounter=$(cat countfile)Adições inteiras simples podem ser feitas no próprio Bash usando a $(( EXPRESSION ))sintaxe. Em seguida, basta escrever o resultado novamente em nosso countfile:
echo "$(( counter + 1 ))" > countfile
Provavelmente, você também deve proteger seu script para o caso que countfileainda não existe e criar um inicializado com o valor 1.
A coisa toda pode ficar assim:
#!/bin/bash
if [[ -f countfile ]] ; then
read counter < countfile
else
counter=0
fi
echo "$(( counter + 1 ))" > countfile
$(…)seja executado antes de qualquer outra coisa (especialmente antes do >). Mas geralmente uso a $(cat countfile 2>/dev/null || echo 0)peça para obter um padrão razoável, caso o arquivo não exista. Poderíamos adicionar um sponge:-) para estar seguro.
flockcomando para evitar condições de corrida. Veja unix.stackexchange.com/a/409276
Apenas deixe o script criar um arquivo de log, adicione, por exemplo, uma linha no seu script no final:
echo "Script has been executed at $(date +\%Y-\%m-\%d) $(date +\%H-\%M-\%S)" >> ~/script.log
Dessa forma, você pode formatar a forma como apresenta a data e a hora, mas se você deseja apenas uma data e hora completas (e HH:MM:SSé um formato aceitável para você), também pode usar:
echo "Script has been executed at $(date +\%F-\%T)" >> ~/script.log
Então você poderia fazer:
wc -l ~/script.log
Que conta os caracteres da nova linha e fornece uma estimativa de quantas linhas estão dentro do arquivo de log. Até isso, você pode ver dentro do arquivo de log, mesmo quando ele foi executado. Para adaptá-lo às suas necessidades, você pode alterar os caminhos e nomes usados para o log. Acabei de fazer um exemplo aqui que salva o arquivo de log ~.
Portanto, por exemplo, você deseja que o script adicione essa contagem à linha que você adicionou no final do script, você pode fazer algo assim no início do 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 mude sua linha no final do script para algo que inclua até essas informações:
echo "Script has been executed $count times at $(date +\%F-\%T)" >> ~/script.log
Essa solução usa a mesma abordagem da resposta do Byte Commander, mas não depende da aritmética do shell ou de outros bashismos.
exec 2>&3 2>/dev/null
read counter < counter.txt || counter=0
exec 3>&2 3>&-
expr "$counter" + 1 > counter.txt
Os redirecionamentos de fluxo
/dev/null(para suprimir a mensagem de erro no redirecionamento subsequente da entrada do readcomando se o arquivo do contador estiver faltando, como esperado),Um arquivo de contador separado tem desvantagens:
Portanto, essa resposta elimina um arquivo de contador separado e coloca a contagem no próprio script bash!
flockgarantias de que, por um breve momento, não é possível que dois usuários executem o script ao mesmo tempo.#!/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
Semelhante à resposta da Videonauth, escrevi uma resposta para o arquivo de log aqui: Script Bash para manter a trilha de auditoria / log de arquivos acessados para log toda vez que os poderes de raiz eram usados com geditou nautilus.
O problema, porém, é que, em vez de usar gksuo script, é nomeado gsue invoca pkexeca maneira "moderna" de usar o sudo na GUI, pelo que me disseram.
Outra vantagem não é apenas a indicação de cada vez que os poderes raiz foram usados, geditmas também registra o nome do arquivo que foi editado. Aqui está o 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
Conteúdo do arquivo de log gsu-log-file-for-geditapós algumas edições:
__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