모든 하위 프로세스가 종료되기 전에 CMD.EXE가 리디렉션된 출력 파일을 해제할 수 있습니까?

모든 하위 프로세스가 종료되기 전에 CMD.EXE가 리디렉션된 출력 파일을 해제할 수 있습니까?

다른 인스턴스를 시작하는 프로그램이 있습니다. 각 인스턴스는 표준 출력 스트림을 다른 파일로 리디렉션합니다. 다음과 같은 일련의 이벤트에 문제가 있습니다.

  1. 명령이 포함된 BAT 파일이 실행됩니다.my_program.exe > output_launcher.txt
  2. my_program.exe는 명령을 사용하여 더 많은 인스턴스를 시작 my_program.exe > output_1.txt하고my_program.exe > output_2.txt
  3. 원래 인스턴스( my_program.exe > output_launcher.txt)는 종료되고 시작된 두 인스턴스( my_program.exe > output_1.txtmy_program.exe > output_2.txt)는 계속 실행됩니다.
  4. #1의 동일한 BAT 파일이 다시 실행됩니다.
  5. 의 새 인스턴스는 my_program.exe > output_launcher.txt"다른 프로세스에서 사용 중이기 때문에 프로세스가 파일에 액세스할 수 없습니다."라는 오류와 함께 실패합니다.

#1의 BAT 파일이 출력을 리디렉션하지 않는 경우 오류가 발생하지 않으며, BAT 파일을 두 번째로 실행하기 전에 시작된 두 인스턴스가 종료되는 경우에도 오류가 발생하지 않습니다.

따라서 모든 하위 프로세스가 완료될 때까지 CMD.EXE가 output_launcher.txt 파일에 대한 독점 권한을 보유하고 있다고 가정합니다.

우선, 그것은 좋은 가정인가?

내가 원하는 것은 각 하위 프로세스가 자체 파일로 리디렉션되기 때문에 원래 인스턴스가 #3에 존재할 때 CMD.EXE가 output_launcher.txt에 대한 권한을 포기한다는 것입니다.

표준 출력을 리디렉션할 때 이것이 가능합니까? 내가 생각할 수 있는 가장 좋은 대안은 실제로 로그 파일 위치를 명령줄 인수로 취하고 표준 출력을 리디렉션하는 대신 내 프로그램에서 직접 파일에 쓰는 것입니다. 하지만 이렇게 하려면 더 많은 작업이 필요하므로 가능하면 해당 경로를 피하고 싶습니다.

감사해요!

편집: 첫 번째 인스턴스가 추가 인스턴스를 시작하는 데 사용하는 실제 명령줄은 다음과 같습니다 start cmd /C "call my_program.exe > output_1.txt". 그런 다음 해당 명령을 "system()" 함수에 전달합니다(my_program.exe는 MSDN C로 작성되었습니다).

도움이 될 수 있는 다른 방식으로 추가 인스턴스를 시작할 수 있을까요?

답변1

몇 가지 간단한 테스트를 거친 후 귀하의 가정이 올바른 것으로 보입니다. 확인하고 싶으시다면 추천드려요프로세스 해커. (상단에 "다운로드" 버튼이 있습니다. 광고에 잘못된 다운로드 링크가 표시되므로 주의하세요.) 해커로 이동하여 핸들 또는 DLL 찾기... (Ctrl-F)

이를 이용하면 무엇이 파일을 사용하고 있는지 쉽게 확인할 수 있으며, 조회를 다시 수행하여 파일이 언제 공개되는지 확인할 수 있습니다.

Process Explorer도 비슷한 작업을 수행할 수 있을 것으로 기대합니다.

고유한 파일 이름으로 작성하는 것이 더 나을 수도 있습니다. 다음을 고려하십시오. 첫 번째 하위 호출은 output_1.txt, 두 번째 하위 호출은 Output_2.txt 대신 어떤 파일이 이미 존재하는지 확인하십시오. 그런 다음 파일을 덮어쓰거나 파일이 사용 중이어서 추가할 수 없어서 문제가 발생하지 않도록 더 높은 수준으로 이동하세요. 운영 체제와 프로그래밍 언어는 고유한 파일 이름을 생성하는 기능을 제공하는 경우가 많습니다.

많은 임시 파일에 쓴 다음 이를 더 적은 수의 파일로 결합할 수 있습니다. 그 아이디어가 완전히 의미가 있는지, 아니면 전혀 의미가 없는지 여부는 프로젝트와 접근 방식에 따라 달라질 수 있습니다.

program.exe에 대한 소스 코드가 있는 경우 "program.exe > 파일 이름"을 실행하는 대신 "program.exe 파일 이름"을 사용하세요. 파일에 빠르게 쓸 수 있는 코드를 프로그램에 배치한 다음 활성 쓰기가 없을 때 더 이상 보류되지 않도록 파일을 닫습니다. (보다 철저한 프로세스는 일부 "잠금"을 수행할 수도 있습니다... 프로그램의 여러 복사본을 실행하고 있으므로 실제로 투자할 가치가 있을 수 있습니다.) printf()를 호출하는 대신 printf만 호출하는 사용자 정의 함수를 사용하십시오. () 지정된 출력 파일이 없으면 파일에 씁니다. 그런 다음 출력 파일을 변경할 때마다 모든 printf() 호출을 변경할 필요 없이 사용자 정의 출력 함수에 전달되는 하나의 변수 값만 변경하면 됩니다. 시간이 좀 더 걸리므로 바람직하지 않을 수도 있다고 말씀하신 것을 알고 있습니다. 하지만 그런 접근 방식을 생각해낸 후 개인적으로 많은 시간과 노력을 절약했다는 사실을 알려 드리겠습니다. 나는 이것이 장기적으로 좋은 해결책이라고 생각합니다.

또는 운영 체제의 로깅 기능을 사용해 보세요. 이는 명령줄에서 명령을 실행하여 수행할 수 있습니다. Unix에서는 "logger"를 실행합니다. MS Windows에서는 다음을 실행하세요.이벤트 생성. 선택한 프로그래밍 언어(MSDN C, 언급한 대로)에서 직접 이를 수행할 수 있는 방법이 있어야 합니다. 출력이 길거나 OS 로그가 복잡해지는 것이 염려되는 경우 이는 이상적이지 않을 수 있습니다. (어떤 곳에서는 OS 로그를 적극적으로 모니터링하는 것으로 알고 있습니다.)

답변2

그것은 합리적인 가정이다.

1) 파일이 다른 응용 프로그램에서 열려 있지 않은지 확인하십시오. 이를 수행하는 합리적인 방법은 .bat 응용 프로그램이 실행되지 않는 동안 파일 이름을 바꾸는 것입니다. 이것이 실패하면 다른 응용 프로그램이 파일을 열어둔 상태입니다.

>>2) 대신 Append Operator를 사용해 >보고 무슨 일이 일어나는지 말해 주실 수 있나요?

관련 정보