동일한 줄을 플러시하는 대신 명령 출력을 새 줄로 분할합니다.

동일한 줄을 플러시하는 대신 명령 출력을 새 줄로 분할합니다.

다음과 관련된 스크립트를 작성하려고 합니다.스냅샷 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사용할 수 있습니다 . 이는 특히 .stdbufsedtr\r\nsed

snapraid sync |
  stdbuf -oL tr '\r' '\n' |
  ts '[%Y-%m-%d %H:%M:%S]' |
  tee -a "$LOG_FILE"

snapraid터미널에 들어가지 않을 때 출력을 버퍼링하는 경우 (라인 기반 버퍼링) 대신 stdbuf버퍼링되지 않은(버퍼링되지 않은) 터미널에서 동일한 방법을 시도해 볼 수 있습니다.stdbuf -o0stdbuf -oL

stdbuf -o0 snapraid sync |
  stdbuf -oL tr '\r' '\n' |
  ts '[%Y-%m-%d %H:%M:%S]' |
  tee -a "$LOG_FILE"

이는 어떤 방법으로든 표준 명령은 아니지만 가능한 경우 응용 프로그램이 버퍼링 하지 않도록 설득하려고 시도 하지만 출력을 손상시키는 것으로 알려진 stdbuf의사 tty를 사용하는 스크립트보다 선호되어야 합니다 .unbufferexpect

-u없음은 표준 옵션입니다 sed.

많은 sed구현에서는 주소가 일치하는 시기를 알 수 있도록 미리 한 줄을 읽습니다 $. 즉, 최종 장치에 도달하더라도 출력이 한 줄 지연됩니다.

ts버퍼링을 명시적으로 비활성화하는 스크립트입니다 perl. $| = 1내 테스트에서 teeGNU는 개체 파일이나 표준 출력이 모두 터미널 장치가 아니었음에도 불구하고 적어도 출력을 버퍼링하지 않았습니다.

그런데, 누구나 쓸 수 있는 디렉터리에 고정된 이름으로 파일을 쓰는 것은 /tmp보안 관점에서 나쁜 습관이므로 피해야 합니다. 이를 사용하여 mktemp자신만의 임시 파일을 확보하거나, 예를 들어 다른 사람이 악의적인 심볼릭 링크를 심을 수 없는 디렉터리에 파일을 쓰십시오.

관련 정보