다음과 관련된 스크립트를 작성하려고 합니다.스냅샷 RAID, 진행률 출력은 snapraid sync
타임스탬프가 지정되고 파일 및 표준 출력에 기록됩니다. 내가 직면하고 있는 문제는 snapraid sync
매초마다 새로 고쳐지는 행에 진행 상황을 출력하는 것입니다. 즉, 스크립트 내에서 실행할 때 남은 출력은 와 같습니다 100% completed, 7737 MB accessed in 0:00
. 명령이 어떻게 실행되었는지 검토할 수 없습니다.
ts
, sed
및 다음 을 사용하여 tee
목표를 부분적으로 달성할 수 있습니다 .
#!/bin/bash
LOG_FILE="/tmp/snapRAID.log"
exec 1>> >(ts '[%Y-%m-%d %H:%M:%S]') 2>&1
snapraid sync | sed -e 's/\r/\n/g' | tee >(ts "[%Y-%m-%d %H:%M:%S]" >> $LOG_FILE)
stdout
그러면 다음 출력이 생성됩니다 /tmp/snapRAID.log
(나머지 출력과 함께 snapraid sync
).
[2023-04-23 16:24:51] 0%, 0 MB
[2023-04-23 16:24:51] 5%, 552 MB
[2023-04-23 16:24:51] 12%, 1332 MB
[2023-04-23 16:24:51] 17%, 1942 MB
[2023-04-23 16:24:51] 21%, 2311 MB
[2023-04-23 16:24:51] 27%, 3044 MB, 622 MB/s, 1188 stripe/s, CPU 14%, 0:00 ETA
[2023-04-23 16:24:51] 35%, 3836 MB, 656 MB/s, 1253 stripe/s, CPU 14%, 0:00 ETA
[2023-04-23 16:24:51] 42%, 4612 MB, 676 MB/s, 1306 stripe/s, CPU 15%, 0:00 ETA
[2023-04-23 16:24:51] 49%, 5005 MB, 636 MB/s, 1334 stripe/s, CPU 15%, 0:00 ETA
[2023-04-23 16:24:51] 58%, 5493 MB, 617 MB/s, 1400 stripe/s, CPU 16%, 0:00 ETA
[2023-04-23 16:24:51] 67%, 5987 MB, 581 MB/s, 1449 stripe/s, CPU 16%, 0:00 ETA
[2023-04-23 16:24:51] 75%, 6415 MB, 564 MB/s, 1470 stripe/s, CPU 16%, 0:00 ETA
[2023-04-23 16:24:51] 80%, 6694 MB, 536 MB/s, 1429 stripe/s, CPU 15%, 0:00 ETA
[2023-04-23 16:24:51] 84%, 6916 MB, 507 MB/s, 1376 stripe/s, CPU 15%, 0:00 ETA
[2023-04-23 16:24:51] 92%, 7314 MB, 498 MB/s, 1388 stripe/s, CPU 15%, 0:00 ETA
[2023-04-23 16:24:51] 97%, 7574 MB, 433 MB/s, 1268 stripe/s, CPU 13%, 0:00 ETA
문제는 이 출력이 실시간이 아니라는 점입니다. snapraid sync
실행이 완료된 후에야 전체 출력이 표준 출력 및 로그 파일에 나타납니다. 요소 를 제거 tee
하고 stdout
. snapraid sync
이 테스트 인스턴스는 몇 초 만에 동기화되지만 이를 실행하려는 컴퓨터에서는 몇 시간이 걸릴 수 있으며, 명령이 실행되는 동안 명령의 진행 상황을 확인하는 동시에 실행하기 전에 발생한 일을 되돌아볼 수 있기를 원합니다. 타임 스탬프를 확인하세요.
나는 성공하지 못한 채 다음 아이디어 중 일부를 시도했습니다.
unbuffer snapraid sync | sed -e 's/\r/\n/g' | tee >(ts "[%Y-%m-%d %H:%M:%S]" >> $LOG_FILE)
snapraid sync | sed -u -e 's/\r/\n/g' | tee >(ts "[%Y-%m-%d %H:%M:%S]" >> $LOG_FILE)
타임스탬프가 포함된 개행 출력이 실시간으로 발생하도록 하는 방법을 아는 사람이 있습니까?
미리 감사드립니다!
답변1
sed
출력이 tty로 전송되지 않으므로 출력을 버퍼링합니다. 일부 구현 에서는 해당 버퍼링을 비활성화하는 옵션을 sed
지원 하거나 , with 또는 with 를 -u
사용할 수 있습니다 . 이는 특히 .stdbuf
sed
tr
\r
\n
sed
snapraid sync |
stdbuf -oL tr '\r' '\n' |
ts '[%Y-%m-%d %H:%M:%S]' |
tee -a "$LOG_FILE"
snapraid
터미널에 들어가지 않을 때 출력을 버퍼링하는 경우 (라인 기반 버퍼링) 대신 stdbuf
버퍼링되지 않은(버퍼링되지 않은) 터미널에서 동일한 방법을 시도해 볼 수 있습니다.stdbuf -o0
stdbuf -oL
stdbuf -o0 snapraid sync |
stdbuf -oL tr '\r' '\n' |
ts '[%Y-%m-%d %H:%M:%S]' |
tee -a "$LOG_FILE"
이는 어떤 방법으로든 표준 명령은 아니지만 가능한 경우 응용 프로그램이 버퍼링 하지 않도록 설득하려고 시도 하지만 출력을 손상시키는 것으로 알려진 stdbuf
의사 tty를 사용하는 스크립트보다 선호되어야 합니다 .unbuffer
expect
-u
없음은 표준 옵션입니다 sed
.
많은 sed
구현에서는 주소가 일치하는 시기를 알 수 있도록 미리 한 줄을 읽습니다 $
. 즉, 최종 장치에 도달하더라도 출력이 한 줄 지연됩니다.
ts
버퍼링을 명시적으로 비활성화하는 스크립트입니다 perl
. $| = 1
내 테스트에서 tee
GNU는 개체 파일이나 표준 출력이 모두 터미널 장치가 아니었음에도 불구하고 적어도 출력을 버퍼링하지 않았습니다.
그런데, 누구나 쓸 수 있는 디렉터리에 고정된 이름으로 파일을 쓰는 것은 /tmp
보안 관점에서 나쁜 습관이므로 피해야 합니다. 이를 사용하여 mktemp
자신만의 임시 파일을 확보하거나, 예를 들어 다른 사람이 악의적인 심볼릭 링크를 심을 수 없는 디렉터리에 파일을 쓰십시오.