배치가 그것을 실행하는 cmd의 우선 순위 만 어떻게 낮출 수 있습니까?


1

길고 CPU를 많이 사용하는 일련의 명령을 실행하는 배치가 있습니다. 언제 완료되는지는 신경 쓰지 않으므로 유휴 CPU주기 만 사용하는 것이 좋습니다. cmd.exe동일한 배치에서 배치 (일부 )를 실행중인 프로세스의 우선 순위를 설정하면 모든 하위 프로세스가 우선 순위를 상속해야합니다. 를 사용하여 프로세스 우선 순위를 변경할wmic 수 있다는 것을 알고 있습니다 . 예를 들면 다음과 같습니다.

wmic process where name="cmd.exe" CALL setpriority "idle"

실제로 작업을 수행하지만 cmd.exe실행중인 다른 인스턴스를 낮추면 항상 적합하지 않을 수도 있습니다.

배치를 실행중인 프로세스를 식별하고 우선 순위만으로 설정하는 방법이 idle있습니까?

명확히하기 위해 : 나는 당신 이이 종류의 배치 또는 .bat낮추기를 요구 할 수 있는 배치에 포함 할 수있는 일반적인 방법을 찾고 있습니다.

이것은 때때로 발견되는 문제이지만, .bat지금 쓰고 있는 특정 에서는 한 번에 하나씩 처리 할 가변 개수의 파일을 전달합니다.

답변:


2

한 가지 방법은 PID ( "프로세스 ID"의 약자)를 찾아서 시작하는 것입니다.

WMIC 프로세스 역할은 우선 순위 설정 이상의 기능을 지원합니다. 세부 사항도 얻을 수 있습니다. 예를 들면 다음과 같습니다 (한 줄로 실행).

WMIC process where name="cmd.exe" get Caption,CommandLine,Name,ParentProcessId,ProcessId /FORMAT:LIST

(자연스럽게 이것은 질문의 샘플과 같은 전통적인 명령 프롬프트에서 실행하기위한 것입니다. PowerShell을 사용하려면 추가 이스케이프가 필요합니다.)

그러나 여러 문제가 발생할 수있는 CMD.EXE 복사본이 여러 개있을 수 있습니다. 배치 파일이 시작되는 방법을 약간 제어 할 수 있으면 더 쉬울 수 있습니다. Dean의 StackOverflow.com 질문, "Bat File에서 실행중인 exe의 프로세스 ID 가져 오기" 는 PID를 환경 변수로 가져 오는 여러 가지 솔루션을 제공합니다. 어떤 솔루션이 자신에게 가장 적합한 지 결정하기 위해 해당 솔루션을 살펴 보는 것이 좋습니다.하지만 여기에는 가능한 한 가지 방법이 있습니다.

C:\> wmic Process WHERE "CommandLine LIKE '%%MyProgWMICflag%%'" Get ParentProcessID /format:list

WMIC 명령에 대한 ParentProcessID가 표시되어야합니다. WMIC는 아마도 셸이라고하는 프로그램의 PID입니다.

이것은 PID를 얻는 위의 하이퍼 링크 된 솔루션 페이지에서 foxidrive의 답변을 기반으로합니다. (이 답변은 원하는 경우 환경 변수로 가져 오는 것을 보여줍니다.)

그런 다음 WHERE 절에 ProcessId를 포함 시키십시오. 예 :

WMIC process where "name='cmd.exe' AND ProcessId='12345'" CALL setpriority "idle"

참고 : 이것은 한 가지 방법 일뿐입니다. 테스트하기에 더 좋은 다른 일반적인 특성이있을 수 있습니다. 다음과 같은 방법으로 확인할 수있는 속성 목록을 볼 수 있습니다.
WMIC /OUTPUT:"Results.txt" Process Get /FORMAT:LIST


따라서 실제 cmd.exePID 를 정확히 지적하기 위해 모두 비등합니다 . 이것은 거의 답입니다. 그러나 지금 나는 이것을 할 수있는 방법을 생각할 수 없습니다. 이 생각을 배경으로 보내겠습니다. 어쩌면 어떤 아이디어가 나타날 수 있습니다.
cdlvcdlv

그렇기 때문에 "배트 파일에서 실행되는 exe의 프로세스 ID 가져 오기" 라는 Dean의 StackOverflow.com 질문에 여러 가지 솔루션이 제공 된다고 언급 한 것입니다 . 어떤 답변 (해당 답변에서 언급)이 가장 편리한 지 추측하고 다른 방법의 세부 정보를 남기지 않고 한 방법에서 정보를 복사하려고 시도하면 아무런 이점이 없습니다. 나는 이것을 조금 더 연주하고 정보를 추가했다 ( "하나의 가능한 접근법"참조)
TOOGAM

나는 이 질문을 발견 하고 노력하고 있었지만 그 %% MyProgWMICflag %% 트릭은 영리합니다!
cdlvcdlv 2016 년

0

START (다른 배치에서)로 배치를 실행해야합니다- 시작 은 별도의 우선 순위를 갖도록 설정할 수 있습니다

START "" batch.bat /B /LOW

어쩌면 나는 잘 설명하지 못했습니다. 이런 식으로 우선 순위가 낮은 프로세스를 시작할 수 있다는 것을 알고 있지만 .bat필자가 작성한 모든 종류 의 런처를 만들어야합니다 . 내가 찾고있는 것은 이와 같은 배치에 포함 할 수있는 일반적인 방법입니다. 또는 .bat호출을 낮추어 배치 할 수 있는 배치입니다 .
cdlvcdlv 2016 년

@cdlvcdlv 나는 prnwatch.com/prio로 재 지명되었습니다 -아마 그것은 당신을 도울 것입니다
gamer0

0

이것은 다른 우선 순위에서 배치 우선 순위를 설정하는 데 사용할 수 있는 작업 입니다. 디렉토리를 디렉토리에 복사 하면 필요할 때 언제든지 호출 할 수 있습니다. TOOGAM 덕분에이를 작성 하는 도구와 방법을 얻을 수있었습니다. 변수를 사용 하면 정확히 지정된 프로세스가 배치의 다른 인스턴스 (정확하지는 않지만 가능한 시나리오)가 아니라 정확히 필요한 것입니다.SetMyPrio.bat MyPrio.bat%PATH%UniqueString

@echo off

GOTO :EndOfReminder

<HELP>

USAGE:

From any batch file or command prompt, write
   CALL MyPrio [/?|/h] [<priority>|get]
to set the priority of the caller cmd. Default for <priority> is idle.

/?, /h        This help.

<priority>    If you want your priority change to 
                 idle          -- no parameter, 64, idle or "idle"
                 below normal  -- 16384 or "below normal"
                 normal        -- 32, normal or "normal"
                 above normal  -- 32768 or "above normal"
                 high priority -- 128 or "high priority"
                 real time     -- 256, realtime or "realtime"
get           Returns current priority as errorlevel

TO DO
   - Parameter error control.
   - Support for Unicode characters in help.
</HELP>

:EndOfReminder
setlocal
set Priority=%~1

if /I ["%Priority%"]==["/h"] ( call :PrintHelp & exit /b )
if ["%Priority%"]==["/?"] ( call :PrintHelp & exit /b )

set UniqueString=%RANDOM%-%RANDOM%-%RANDOM%-%RANDOM%-%RANDOM%

if ["%Priority%"]==["get"] for /f "usebackq tokens=2 delims==" %%a in (`wmic Process WHERE "name='cmd.exe' AND CommandLine LIKE '%%%UniqueString%%%'" Get Priority /format:LIST`) do exit /b %%a

if not defined Priority set Priority=idle
for /f "usebackq tokens=2 delims==" %%a in (`wmic Process WHERE "name='cmd.exe' AND CommandLine LIKE '%%%UniqueString%%%'" Get ParentProcessID /format:LIST`) do set myPID=%%a
wmic process where "ProcessId='%myPID%'" CALL setpriority "%Priority%" > nul 2>&1

endlocal
goto :eof

:PrintHelp
setlocal DisableDelayedExpansion
call :eln 0
set "levelerror=^%%errorlevel^%%"
for /F "delims=" %%a in ('find /v /n "" "%~f0"') do (
   set "line=%%a"

   REM We store errorlevel in tmpel because setlocal will set errorlevel to 0...
   call set tmpel=%levelerror%
   setlocal EnableDelayedExpansion
   REM ... and now we restore it
   REM %levelerror% was expanded to %errorlevel% before running the iteration
   REM and the CALL SET allows actual errorlevel be stored in tmpel
   REM Finally, we set errorlevel again
   call :eln !tmpel!

   set "line=!line:*]=!"

   if /i "!line!"=="</HELP>" exit /b 0
   if errorlevel 1 echo(!line!
   if /i "!line!"=="<HELP>" call :eln 1
REM errorlevel is the only value that survives the following endlocal
   endlocal
)
exit /b 1

:eln
REM Sets errorlevel to %1
exit /b %1

편집 (2018-06-12)

  • 로 이름을 변경 MyPrio , 옵션을 추가 /?, /h하고 get.
  • 옵션 /?/h당신 사이의 알림에 쓰기 텍스트 인쇄 <HELP></HELP>. 이 방법은 필요한 다른 배치에서 재사용 할 수 있습니다.

MyPrio.bat배치 시작시 전화를 걸면 명령 줄에서 시작하거나 매개 변수가되는 Windows 탐색기에서 파일을 끌어다 놓아도 배치의 모든 부분 (및 하위 프로세스)이 실행됩니다. 원하는 우선 순위.

예를 들면 다음과 같습니다.

@echo off
call MyPrio

REM Here comes a set of commands that will run with idle priority.

call MyPrio normal

REM Here may come some interactive part to request information needed to continue.

call MyPrio

REM Back to idle (or put any other priority you prefer).

call MyPrio normal

REM You may want to set the priority to normal at the end just in case you call the batch from a command line.

코멘트

가능한 모든 옵션 PrioTest.bat으로 테스트 할 배치 이름 을 지정 하고 MyPrio.bat모든 호출이 우선 순위를 다른 것으로 변경하도록 주문했습니다. 나는 다음과 같은 서브 루틴 ( :test1)을 만들었다 :

1. 현재 우선 순위를 가져 와서에 저장하십시오 myPrioBefore.
2.MyPrio 테스트 매개 변수를 사용하여 호출 합니다.
3. 새로운 우선 순위를 가져 와서에 저장하십시오 myPrioAfter.
4. 숨겨진를 시작합니다 ping -t localhost.
5. 의 우선 순위와 PID를 가져옵니다 ping공정과에 저장 pingPrio하고 pingPID.
6. 값 인쇄 myPrioBefore, 호출 MyPrio, myPrioAfterpingPrio.
7. 시작된 것을 종료합니다 ping(다른 것이 아닌지 확인).

@echo off

setlocal

set UniqueString=%RANDOM%-%RANDOM%-%RANDOM%-%RANDOM%-%RANDOM%
for /f "usebackq tokens=2 delims==" %%a in (`wmic Process WHERE "name='cmd.exe' AND CommandLine LIKE '%%%UniqueString%%%'" Get ParentProcessID /format:LIST`) do set myPID=%%a
for %%a in (64 16384 32 32768 128 256 idle "below normal" none normal "idle" "normal" "above normal" realtime "high priority" "realtime") do call :test1 %%a
CALL MyPrio normal

endlocal
goto :eof

:test1
for /f "usebackq tokens=2 delims==" %%b in (`wmic Process WHERE "ProcessID='%%myPID%%'" Get Priority /format:LIST`) do set myPrioBefore=%%b
if [%1]==[none] ( call MyPrio ) else ( call MyPrio %1 )
for /f "usebackq tokens=2 delims==" %%b in (`wmic Process WHERE "ProcessID='%%myPID%%'" Get Priority /format:LIST`) do set myPrioAfter=%%b
start "" /b ping -t localhost > nul
for /f "usebackq tokens=2 delims==" %%b in (`wmic Process WHERE "name='ping.exe' AND ParentProcessID='%%myPID%%'" Get Priority /format:LIST`) do set pingPrio=%%b
for /f "usebackq tokens=2 delims==" %%b in (`wmic Process WHERE "name='ping.exe' AND ParentProcessID='%%myPID%%'" Get ProcessID /format:LIST`) do set pingPID=%%b
echo myPrioBefore==%myPrioBefore% / CALL MyPrio %1 / myPrioAfter==%myPrioAfter% / pingPrio==%pingPrio%
taskkill /f /pid %pingPID% > nul
exit /b

테스터 배치의 출력입니다.

myPrioBefore==4 / CALL MyPrio 64 / myPrioAfter==4 / pingPrio==4
myPrioBefore==4 / CALL MyPrio 16384 / myPrioAfter==6 / pingPrio==6
myPrioBefore==6 / CALL MyPrio 32 / myPrioAfter==8 / pingPrio==8
myPrioBefore==8 / CALL MyPrio 32768 / myPrioAfter==10 / pingPrio==8
myPrioBefore==10 / CALL MyPrio 128 / myPrioAfter==13 / pingPrio==8
myPrioBefore==13 / CALL MyPrio 256 / myPrioAfter==13 / pingPrio==8
myPrioBefore==13 / CALL MyPrio idle / myPrioAfter==4 / pingPrio==4
myPrioBefore==4 / CALL MyPrio "below normal" / myPrioAfter==6 / pingPrio==6
myPrioBefore==6 / CALL MyPrio none / myPrioAfter==4 / pingPrio==4
myPrioBefore==4 / CALL MyPrio normal / myPrioAfter==8 / pingPrio==8
myPrioBefore==8 / CALL MyPrio "idle" / myPrioAfter==4 / pingPrio==4
myPrioBefore==4 / CALL MyPrio "normal" / myPrioAfter==8 / pingPrio==8
myPrioBefore==8 / CALL MyPrio "above normal" / myPrioAfter==10 / pingPrio==8
myPrioBefore==10 / CALL MyPrio realtime / myPrioAfter==13 / pingPrio==8
myPrioBefore==13 / CALL MyPrio "high priority" / myPrioAfter==13 / pingPrio==8
myPrioBefore==13 / CALL MyPrio "realtime" / myPrioAfter==13 / pingPrio==8

보시다시피 myPrioAfter, 호출에서 요청한 것과 일치하지 않으며 때로는 의 우선 순위가 ping부모와 같지 cmd않으므로 더 많은 값이 있어야합니다 (5 번째 줄을보십시오 : 현재 우선 순위는 10, 128을 요청하십시오. 우선 순위는 13이고 하위 프로세스는 8입니다. 죄송합니다.). 또한 realtime효과가없는 것 같습니다 (관리자 권한 필요).


0

여기에 내가 취하는 것이 있습니다 : 현재 프로세스 우선 순위를 낮추는 대신 우선 순위 cmd.exe가 낮은 새 인스턴스를 생성하여 배치 파일을 다시 시작하십시오 . 환경은 (자동적으로) 상속 될 것이며, 처음에 가까워지면 처리를 제외하고 는 거의 "동일한"행동을 할 것입니다 Ctrl+c( 대신 start /b사용 을 금지 Ctrl+Break합니다). 이것은 추가 cmd.exe인스턴스 (및 관련 conhost.exe) 의 (낮은) 비용으로 추가 종속성을 도입하지 않습니다 .

이 스 니펫을 복사하여 붙여 넣기 만하면됩니다.

rem | reduce process priority (uses an additional cmd.exe instance)
if not "%TARGET_LABEL%"=="" goto %TARGET_LABEL%
set TARGET_LABEL=RunLowPriority
start "" /b /belownormal /wait cmd /d /c "%~dpnx0" %*
goto :EOF
:RunLowPriority

일어나고있는 일 :

  • [2 번째 인스턴스] 이전 설정이 감지되었습니다. 원하는 위치로 이동합니다 ( RunLowPriority)
  • [첫 번째 인스턴스] RunLowPriority두 번째 인스턴스의 점프 대상 ( )을 설정 합니다.
  • [첫 번째 인스턴스] 두 번째 인스턴스를 시작합니다
    • 보통 우선 순위 이하로 사용
    • 새 콘솔을 시작하지 않고 두 번째 인스턴스가 끝날 때까지 기다리십시오
    • "놀람"(공백 등)을 피하려면 따옴표로 전체 경로를 사용하십시오.
    • 모든 매개 변수를 전달 ( %*)
  • [첫 번째 인스턴스] 두 번째 인스턴스가 끝나면 종료

두 개의 명령 프롬프트 인스턴스를 사용하는 부수적 인 효과 Ctrl+Break두 개의 배치 작업 종료 (Y / N)를 표시합니까? -대화식으로 스크립트를 실행할 때 문제가되지 않지만 (예 : Windows 탐색기) 기존 명령 프롬프트에서 실행할 때 약간 이상합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.