스크립트가 실행 된 횟수만큼 별도의 파일에 로그인하도록하려면 어떻게해야합니까? 몇 번이나

이 스크립트를 몇 번이나 실행했는지 파일에 쓰는 스크립트를 작성해야합니다.

어떻게해야합니까?



답변

countfile실행 카운터를 나타내는 하나의 단일 숫자 만 포함 하는 단일 파일 을 원한다고 가정합니다 .

이 카운터를 쉘 변수로 읽을 수 있습니다 ( $counter예 : 다음 행 중 하나 사용).

  • read counter < countfile
  • counter=$(cat countfile)

$(( EXPRESSION ))구문을 사용하여 Bash 자체에서 간단한 정수 추가를 수행 할 수 있습니다 . 그런 다음 간단히 결과를 우리 countfile에게 다시 쓰십시오 .

echo "$(( counter + 1 ))" > countfile

countfile아직 존재하지 않는 경우 스크립트를 보호 하고 값 1로 초기화 된 스크립트를 작성해야합니다.

모든 것이 다음과 같이 보일 수 있습니다.

#!/bin/bash
if [[ -f countfile ]] ; then
    read counter < countfile
else
    counter=0
fi
echo "$(( counter + 1 ))" > countfile


답변

스크립트가 로그 파일을 작성하도록하고 예를 들어 스크립트 끝에 줄을 추가하십시오.

echo "Script has been executed at $(date +\%Y-\%m-\%d) $(date +\%H-\%M-\%S)" >> ~/script.log

이 방법을 사용하면 날짜와 시간을 표시하는 방식을 직접 지정할 수 있지만 전체 날짜와 시간으로 가고 싶을 때 (그리고 HH:MM:SS허용되는 형식) 다음과 같이 간단하게 사용할 수 있습니다.

echo "Script has been executed at $(date +\%F-\%T)" >> ~/script.log

그럼 당신은 할 수 있습니다 :

wc -l ~/script.log

개행 문자를 계산하고 로그 파일에 몇 줄이 있는지 추정합니다. 그것까지는 로그 파일이 실행될 때조차 볼 수 있습니다. 필요에 맞게 조정하기 위해 로깅에 사용되는 경로와 이름을 변경할 수 있습니다. 방금 로그 파일을에 저장하는 예를 보았습니다 ~.

예를 들어 스크립트 끝에 스크립트에 추가 한 줄에이 개수를 추가하려면 스크립트 시작시 다음과 같이 할 수 있습니다.

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"

그리고 스크립트 끝의 줄을 해당 정보를 포함하는 것으로 변경하십시오.

echo "Script has been executed $count times at $(date +\%F-\%T)" >> ~/script.log


답변

이 솔루션은 Byte Commander의 답변 과 동일한 접근 방식을 사용 하지만 쉘 산술 또는 다른 Bashism에 의존하지 않습니다.

exec 2>&3 2>/dev/null
read counter < counter.txt || counter=0
exec 3>&2 3>&-
expr "$counter" + 1 > counter.txt

스트림 리디렉션

  1. 표준 오류 스트림 (2)을 다른 파일 설명자 (3)에 복제
  2. 카운터 파일이 예상치 못한 경우 명령 /dev/null입력의 후속 경로 재 지정에서 오류 메시지를 표시하지 않으려면 (2)를 경로 재 지정으로 바꾸십시오 read.
  3. 나중에 원래 표준 오류 스트림 (현재 3)을 다시 제자리에 복제합니다 (2).
  4. 표준 오류 스트림 (3)의 사본을 닫습니다.

답변

다른 접근법

별도의 카운터 파일에는 다음과 같은 단점이 있습니다.

  • 각 카운터 파일에 4096 바이트 (또는 블록 크기에 관계없이)가 필요합니다.
  • bash 스크립트에서 파일 이름을 찾은 다음 파일을 열어 개수를 확인해야합니다.
  • 파일 잠금 (다른 답변에서는)이 없으므로 두 사람이 동시에 카운터를 업데이트 할 수 있습니다 (Byte Commander의 답변 아래 주석에서 경쟁 조건이라고 함).

따라서이 답변은 별도의 카운터 파일을 없애고 bash 스크립트 자체에 카운트를 넣습니다!

  • bash 스크립트 자체에 카운터를 넣으면 스크립트 자체에서 몇 번 실행되었는지 확인할 수 있습니다.
  • 를 사용하면 flock잠시 동안 두 명의 사용자가 동시에 스크립트를 실행할 수 없습니다.
  • 카운터 파일 이름은 하드 코딩되지 않았으므로 다른 스크립트에 대한 코드를 변경할 필요가 없으므로 간단히 소스 코드를 작성하거나 스텁 / 상용구 파일에서 복사하여 붙여 넣을 수 있습니다.

코드

#!/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

로그 파일을 사용하는 다른 접근법

Videonauth의 답변과 비슷하게 여기에 로그 파일 답변을 썼습니다 : 또는 루트 전원을 사용할 때마다 기록하기 위해 액세스 한 파일의 감사 추적 / 로그를 유지하는 Bash 스크립트 .geditnautilus

그러나 catch gksu는 스크립트를 사용 하는 것이 아니라 GUI에서 sudo를 사용하는 “현대적인”방식을 gsu호출 pkexec하므로 이름을 듣습니다.

또 다른 장점은 루트 전원을 사용할 때마다 말할 gedit뿐 아니라 편집 된 파일 이름을 기록한다는 것입니다. 코드는 다음과 같습니다.

~/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

gsu-log-file-for-gedit몇 번의 편집 후 로그 파일의 내용 :

__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"


답변