루프에서 지속적으로 스크립트를 실행하여 변수가 사용될 때마다 최신 상태가 되도록 백그라운드에서 변수를 업데이트하려고 합니다. 거의 한 시간 동안 검색한 결과 아무 것도 발견되지 않았습니다. 누군가 나보다 먼저 이 작업을 수행하고 싶어할 것 같았기 때문에 놀라운 일이었습니다.
$SESSIONLENGTH
내 스크립트는 세션 길이의 형식화된 문자열로 설정되어야 합니다 ...
#!/bin/bash
while true
do
SECONDSINSESSION=$SECONDS
SECONDSINMINUTE=60
SECONDSINHOUR=3600
SECONDSINDAY=86400
DAYSINSESSION=$(expr "$SECONDSINSESSION" / "$SECONDSINDAY")
DAY_REMAINDER=$(expr "$SECONDSINSESSION" % "$SECONDSINDAY")
HOURSINSESSION=$(expr "$DAY_REMAINDER" / "$SECONDSINHOUR")
HOUR_REMAINDER=$(expr "$DAY_REMAINDER" % "$SECONDSINHOUR")
MINUTESINSESSION=$(expr "$HOUR_REMAINDER" / "$SECONDSINMINUTE")
SECONDSINSESSION=$(expr "$HOUR_REMAINDER" % "$SECONDSINMINUTE")
SESSIONLENGTH="$DAYSINSESSION days, $HOURSINSESSION hours, $MINUTESINSESSION minutes, and $SECONDSINSESSION seconds."
sleep 1
done &
따라서 실행 중인지 확인 jobs
하고 사용하면 echo $SESSIONLENGTH
값이 업데이트되지 않거나 전혀 존재하지 않습니다.
누구든지 도와줄 수 있나요?
source
빠른 편집 : 이 스크립트에는 .
.
답변1
OP의 문제를 해결한 후에는 문제를 설명하고 해결책을 선택해야겠다고 생각했습니다.
기본 스크립트를 작성한 후 source
함수(또는 해당 별칭 )를 사용하여 .
테스트합니다 . 이 경우 스크립트는 정상적으로 실행됩니다. 쉘 변수가 쉘 프로세스 내에 있기 때문에 작동합니다.
백그라운드 프로세스로 실행(또는 단순히 명령으로 호출)되면 스크립트는 셸 프로세스에서 분기된 별도의 프로세스로 실행됩니다. 쉘 프로세스는 새 프로세스의 변수에 대해 아무것도 모릅니다. 이유를 설명하십시오.
값이 업데이트되지 않았거나 전혀 존재하지 않습니다.
두 프로세스는 다양한 방법으로 통신할 수 있지만 채팅에서 선택한 프로세스는 임시 파일을 사용하고 있습니다. 명령 프롬프트 또는 다른 스크립트에서 OP는 cat myfile
변수의 최신 값만 볼 수 있습니다.
이 방법은 이런 상황에 적합합니다.
- OP의 현재 전문 지식 수준과 일치합니다.
- 낮은 데이터 볼륨
- 성능 기대치는 더 낮습니다.
파일 시스템이 동시성 문제를 처리하고 있으며 OP는 이 경우 경쟁 조건 및 기타 동시성 문제에 관심이 없다는 것을 확인했습니다.
한 번에 하나의 스크립트 복사본만 실행할 수 있는 경우 파일 이름은 상수일 수 있습니다. 그렇지 않으면 임시 파일을 할당해야 합니다. 대부분의 쉘에는 임시 파일을 할당하는 방법이 있습니다. 이것이 프로덕션 시나리오에 더 가깝다면 스크립트는 오래된 파일을 정리하는 데 약간의 노력을 기울여야 합니다.
답변2
bash
당신이 trap
사용할 때디버그SESSIONLENGTH
각 명령 전에 다시 계산되도록 신호를 보냅니다 .
trap 'source /path/to/sessionlength' DEBUG
소스 스크립트는 주변 합계 부분이 sessionlength
아닌 루프의 내용만 있으면 됩니다 .while
sleep
SECONDSINSESSION=$SECONDS
SECONDSINMINUTE=60
SECONDSINHOUR=3600
SECONDSINDAY=86400
DAYSINSESSION=$(expr "$SECONDSINSESSION" / "$SECONDSINDAY")
DAY_REMAINDER=$(expr "$SECONDSINSESSION" % "$SECONDSINDAY")
HOURSINSESSION=$(expr "$DAY_REMAINDER" / "$SECONDSINHOUR")
HOUR_REMAINDER=$(expr "$DAY_REMAINDER" % "$SECONDSINHOUR")
MINUTESINSESSION=$(expr "$HOUR_REMAINDER" / "$SECONDSINMINUTE")
SECONDSINSESSION=$(expr "$HOUR_REMAINDER" % "$SECONDSINMINUTE")
SESSIONLENGTH="$DAYSINSESSION days, $HOURSINSESSION hours, $MINUTESINSESSION minutes, and $SECONDSINSESSION seconds."
bash
도 가능산술 확장, 따라서 다음을 expr
사용하여 매번 6개의 프로세스가 생성되는 것을 피할 수 있습니다.
DAYSINSESSION=$((SECONDSINSESSION/SECONDSINDAY))
등.
답변3
스크립트/방법에 몇 가지 기술적인 문제가 있지만 지금은 기술적 세부 사항을 잊어버리고 직관적인 수준에서 원하는 계산 프로세스를 설정한 다음 미래의 어느 시점에대화형으로변수 값을 직접 참조하여 프로세스가 어떻게 진행되는지 쿼리합니다.
bash 쉘은 다음과 같기 때문에 bash에서는 이 작업을 수행할 수 없습니다.동기화언어 해석기, 이는 bash 프로세스가 while
루프를 실행하는 동안 이를 중단하고 다음과 같은 프로그래밍을 말할 수 없음을 의미합니다.
"안녕 bash, 하던 일을 멈추고 메모리(변수
$SESSIONLENGTH
)에 액세스한 다음 그 값을 화면에 인쇄하고 하던 일을 계속하세요."
하고 싶은 일은 해결될 수 있다동시성비동기(nodejs, nginx) 플랫폼이나 이벤트 루프(예: 웹 브라우저의 vim 또는 javascript)를 실행하는 단일 스레드 프로세스에서 수행하는 작업 유형도 있습니다.
~에서위키피디아 동시성기사
동시 시스템은 다른 모든 계산이 완료될 때까지 기다리지 않고 여러 계산이 동시에 발생할 수 있는 시스템입니다.
한정자를 추가하겠습니다.또는 적어도 두 개 이상의 계산이 동시에 진행되는 것처럼 사용자에게 나타납니다.
그렇다면 Bash에서 무엇을 할 수 있나요? 제안된 대로 bash가 출력을 다른 곳으로 보내고 별도의 프로세스에서 데이터를 읽도록 하거나 수정된 버전의 코드를 파일에 넣을 수 있습니다.
sessionstate.sh
for i in seq 1 2 3 4 5
do
SECONDSINSESSION=$SECONDS
SECONDSINMINUTE=60
SECONDSINHOUR=3600
SECONDSINDAY=86400
DAYSINSESSION=$(expr "$SECONDSINSESSION" / "$SECONDSINDAY")
DAY_REMAINDER=$(expr "$SECONDSINSESSION" % "$SECONDSINDAY")
HOURSINSESSION=$(expr "$DAY_REMAINDER" / "$SECONDSINHOUR")
HOUR_REMAINDER=$(expr "$DAY_REMAINDER" % "$SECONDSINHOUR")
MINUTESINSESSION=$(expr "$HOUR_REMAINDER" / "$SECONDSINMINUTE")
SECONDSINSESSION=$(expr "$HOUR_REMAINDER" % "$SECONDSINMINUTE")
SESSIONLENGTH="$DAYSINSESSION days, $HOURSINSESSION hours, $MINUTESINSESSION minutes, and $SECONDSINSESSION seconds."
echo $SESSIONLENGTH
sleep 2
done
그런 다음 출처:
$ source session_state.sh
0 days, 0 hours, 46 minutes, and 26 seconds.
0 days, 0 hours, 46 minutes, and 28 seconds.
0 days, 0 hours, 46 minutes, and 30 seconds.
0 days, 0 hours, 46 minutes, and 32 seconds.
0 days, 0 hours, 46 minutes, and 34 seconds.
0 days, 0 hours, 46 minutes, and 36 seconds.
그런 다음 변수를 쿼리합니다.
$ echo $SESSIONLENGTH
0 days, 0 hours, 46 minutes, and 36 seconds.
변수의 최종 상태를 얻을 수 있지만 프로세스가 완료된 후에만 가능합니다.
동기식 단일 스레드 셸에서 처음에 원하는 이론적 솔루션 중 하나는 다음과 같습니다.
- 만들다두 번째 공정키보드 입력 모니터링
- bash에는 사전 구축된 준비가 있으므로 두 번째 프로세스는
- 대기줄귀하의 사용자는 bash가 실행될 때 요청을 생성합니다.
- 현재 프레임/코드 단위를 완료하면
- 사용자 요청 대기열을 확인하고,
- 실행한 다음
- 중단한 부분부터 계속
다시 말해서이벤트 루프.
답변4
귀하의 요구 사항을 이해하므로 스크립트가 얼마나 오랫동안 실행되었는지 알고 싶습니다.
스크립트가 시작될 때 파일을 생성하면 시작 시간이 표시됩니다. 에포크 이후 크론드 시작 시간의 예:
$ stat -c %Y /var/run/crond.pid
1447709241
crond가 시작된 이후 두 번째:
$ echo $(( $(date +%s)-$(stat -c %Y /var/run/crond.pid) ))
21740420
날짜로 표시:
$ date -d @$(( $(date +%s)-$(stat -c %Y /var/run/crond.pid) )) +%F\ %T
1970-09-09 16:09:56
변수를 읽어야 하는 프로그램이 위 계산을 수행할 수 없는 경우 파일에 $SESSIONLENGTH를 작성해야 하며, 그런 다음 다른 프로세스에서 이를 읽어야 합니다.