Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

iisreset 후에도 이전에 설정한 전역 환경 변수가 w3wp.exe에 적용되는 문제

윈도우 운영체제에서 전역 환경 변수는 다음의 레지스트리 경로에 설정할 수 있습니다.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment

가령 저 경로에 REG_SZ 유형으로 "TEST"라는 이름의 환경 변수를 "1"로 새롭게 생성했다고 가정해 보겠습니다. 이러한 변화는 현재 실행 중인 프로세스들에게는 알려지지 않습니다. 그리고 이전 글에서 설명한 방법으로 그 목적은 달성할 수 있습니다.

C# - 환경 변수의 변화를 알리는 WM_SETTINGCHANGE Win32 메시지 사용법
; https://www.sysnet.pe.kr/2/0/13027

만약, 저 메시지 수신을 대응하지 않는 프로세스라면, 어쩔 수 없이 프로세스를 다시 시작해야 하는 것입니다.

그런데, 여기서 한 가지 문제가 더 있습니다. 바로, 윈도우 운영체제에서 환경 변수는 부모 프로세스의 것을 물려받는다는 점입니다. 이것이 문제가 되는 대표적인 유형이 바로 웹 응용 프로그램을 호스팅하는 w3wp.exe입니다.

w3wp.exe 프로세스는 해당 EXE가 속한 Application Pool을 "재생(Recycle)"시키면 w3wp.exe 프로세스도 내려갔다가 다시 올라오는데요, 재미있는 것은 이때 레지스트리의 설정을 반영하지 못한다는 점입니다. 왜냐하면, 재생(Recycle) 작업은 IIS 서비스를 관리하는 svchost.exe 프로세스가 관장하는데, 이 때문에 w3wp.exe의 직계 부모 프로세스는 svchost.exe가 되고, 결국 svchost.exe의 환경 변수를 그대로 상속받기 때문입니다.

따라서, w3wp.exe의 환경 변수를 새롭게 반영하려면 그것의 부모 프로세스인 svchost.exe까지 완전히 내렸다가 다시 올리는 "iisreset" 명령어를 사용해야 합니다.

참고로, 서비스 관리자에 W3SVC(World Wide Web Publishing 서비스)라고 알려진 서비스를 재시작하면 svchost.exe가 아닌, 그 하위의 모든 w3wp.exe를 재시작하는 역할을 합니다. 즉, 특정 AppPool이 아닌, 모든 AppPool을 재생하는 것과 같은 역할입니다. 반면, "WAS(Windows Process Activation Service)" 서비스를 재시작하면 svchost.exe까지 재시작하는 효과를 갖는데 사실상 iisreset과 유사합니다.




그런데, 간혹 특정 PC에서는 iisreset을 해도 여전히 이전과 동일한 환경 변수를 유지하는 경우가 있습니다. 재현은 다음과 같이 해볼 수 있습니다.

  1. 전역 환경 설정에 TEST=1을 설정
  2. iisreset
  3. 새롭게 설정한 TEST=1 환경 변수는 w3wp.exe에 적용됨
  4. 전역 환경 설정에서 TEST=1을 제거
  5. iisreset
  6. 새롭게 시작한 w3wp.exe에는 여전히 TEST=1 환경 변수가 존재

즉, 전역 환경 설정에서 제거한 TEST=1 환경 변수가 (재부팅하기 전까지는) 삭제되지 않는 것입니다.

이때의 (WAS 서비스인) svchost.exe 프로세스를 Process Explorer를 통해 확인해 보면 그 프로세스 자체에서 이미 환경 변수의 반영이 안 되었다는 것을 알 수 있습니다.

어떻게 생각하면, svchost.exe 역시 그 상위의 프로세스, 즉 SCM(Service Control Manager)이라는 NT 서비스 관리자 프로세스 역할을 하는 services.exe 프로세스 때문이라고 볼 수도 있습니다.

즉, services.exe는 전역 환경 변수가 바뀐 이후 재실행하지 않았으므로 여전히 기존 환경 변수를 보유하고 있으며, 그 상태에서 하위 프로세스인 (WAS를 호스팅하는) svchost.exe를 재시작하는 것이므로 services.exe의 환경 변수를 그대로 상속받게 되는 것입니다.

여기서 재미있는 것은, 일반적인 컴퓨터에서는 저런 상황이 발생하지 않습니다. 정확한 문서를 확인한 것은 아니지만, 마이크로소프트는 services.exe의 경우 하위 프로세스를 실행할 때 1) 환경 변수를 상속하지 않도록 만들거나, 2) 전역 환경 변수의 변화를 받아들이는 식의 작업이 되어 있는 것처럼 동작합니다.

실제로, 대부분의 PC에서 iisreset을 하면 services.exe의 환경 변수에 상관없이 전역 환경 변수 레지스트리의 변화를 반영해 (WAS 서비스인) svchost.exe가 실행이 됩니다.

그런데, 유독 특정 PC에서만 ^^; 그 동작을 하지 않고 있는 것입니다.




이 문제를 다른 식으로 재현해 볼까요? ^^

여기서 해당 svchost.exe는 Local SYSTEM 권한으로 동작하는데요, 실제로 일반 프로세스를 그 권한으로 실행해 보면,

c:\temp> psexec -s -i cmd.exe /K set

svchost.exe가 가지고 있던 환경 변수가 그대로 동일하게 cmd.exe에도 적용된 것을 확인할 수 있습니다.

여기서 더욱 재미있는 것은, iisreset 명령어는 다음의 실행 파일을 구동하는 것에 불과한데,

C:\Windows\System32\inetsrv\iisrstas.exe

이때 iisrstas.exe 프로세스의 부모 프로세스는 (services.exe를 부모로 둔) DcomLaunch 서비스를 대행하는 svchost.exe이고, 그것 역시 예전 환경 변수 구성을 담고 있지만 iisrstas.exe 프로세스를 Process Explorer로 확인해 보면 (w3wp.exe와는 달리) 새롭게 변경된 전역 환경 변수 구성을 반영하고 있다는 점입니다.

물론, 차이점은 있습니다. 실행된 iisrstas.exe의 "USERNAME"은 (iisreset을 관리자 권한으로 실행하므로) Administrator인 반면, w3wp.exe의 부모인 svchost.exe는 Local SYSTEM이라는 것입니다.

그러니까, 사용자 계정 권한에 따라 Local SYSTEM 환경에서는 (레지스트리에 설정된) 새로운 전역 환경 변수 설정을 반영하지 못하고 있는 것입니다. 정리해 보면, services.exe가 환경 변수를 정상적으로 처리하지 못하는 것은 아닌 듯하고, 단지 Local SYSTEM 계정으로 실행되는 프로세스가 정상적으로 환경 변수를 적용하지 못하는 것입니다.




일단, 이 문제의 해결책은 저도 모르겠습니다. ^^; 모든 윈도우 PC가 그런 것도 아니고, 몇몇 사례에서만 이런 현상이 발생하고 있는데 약간의 특이점이라면 최근에 저 현상을 접한 윈도우 PC가 AhnLab이 설치되어 있다는 정도입니다. 앞으로 또 유사한 사례가 나오면 환경 구성을 유심히 봐야겠습니다. ^^;

단지, 우회 방법 정도는 살펴볼 수 있습니다. 위에서 제가 언급한 TEST=1 변수가 삭제되지 않는 문제는, LOCAL SYSTEM 전용 레지스트리의 경로에서,

Computer\HKEY_USERS\S-1-5-18\Environment

TEST 환경 변수를 정의하고 값만 설정해 두지 않으면 됩니다. 즉, iisreset 후 생성되는 w3wp.exe 프로세스가 저 레지스트리의 환경 변수는 정상적으로 반영해서 올라오는 것입니다.

저 방법을 쓰는 것이 하나 껄끄러운 점이 있다면, 저런 조치를 취했다는 것을 행여 잊어버린다거나 하면, 이후 "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" 환경 변수에 TEST=1을 설정해도 Local SYSTEM 계정의 프로세스에만 절대로 반영이 안 되는 것 같은 (당연하지만) 희한한 현상을 겪을 수 있다는 점입니다.




참고로, 다른 프로세스의 환경 변수 설정을 코드로 해결하는 방법은 예전에 설명한 적이 있습니다. ^^

Appinit_Dlls로 구현한 환경 변수 설정 DLL
; https://www.sysnet.pe.kr/2/0/883




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 11/21/2022]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 121  122  123  124  125  126  127  128  129  130  131  [132]  133  134  135  ...
NoWriterDateCnt.TitleFile(s)
1788정성태10/22/201424255VC++: 82. COM 프로그래밍에서 HRESULT 타입의 S_FALSE는 실패일까요? 성공일까요? [2]
1787정성태10/22/201432535오류 유형: 252. COM 개체 등록시 0x8002801C 오류가 발생한다면?
1786정성태10/22/201434032디버깅 기술: 65. 프로세스 비정상 종료 시 "Debug Diagnostic Tool"를 이용해 덤프를 남기는 방법 [3]파일 다운로드1
1785정성태10/22/201423131오류 유형: 251. 이벤트 로그 - Load control template file /_controltemplates/TaxonomyPicker.ascx failed [1]
1784정성태10/22/201430710.NET Framework: 472. C/C++과 C# 사이의 메모리 할당/해제 방법파일 다운로드1
1783정성태10/21/201424495VC++: 81. 프로그래밍에서 borrowing의 개념
1782정성태10/21/201421259오류 유형: 250. 이벤트 로그 - Application Server job failed for service instance Microsoft.Office.Server.Search.Administration.SearchServiceInstance
1781정성태10/21/201421987디버깅 기술: 64. new/delete의 짝이 맞는 경우에도 메모리 누수가 발생한다면?
1780정성태10/15/201425818오류 유형: 249. The application-specific permission settings do not grant Local Activation permission for the COM Server application with CLSID
1779정성태10/15/201421057오류 유형: 248. Active Directory에서 OU가 지워지지 않는 경우
1778정성태10/10/201419483오류 유형: 247. The Netlogon service could not create server share C:\Windows\SYSVOL\sysvol\[도메인명]\SCRIPTS.
1777정성태10/10/201422505오류 유형: 246. The processing of Group Policy failed. Windows attempted to read the file \\[도메인]\sysvol\[도메인]\Policies\{...GUID...}\gpt.ini
1776정성태10/10/201419595오류 유형: 245. 이벤트 로그 - Name resolution for the name _ldap._tcp.dc._msdcs.[도메인명]. timed out after none of the configured DNS servers responded.
1775정성태10/9/201420818오류 유형: 244. Visual Studio 디버깅 (2) - Unable to break execution. This process is not currently executing the type of code that you selected to debug.
1774정성태10/9/201427732개발 환경 구성: 246. IIS 작업자 프로세스의 20분 자동 재생(Recycle)을 끄는 방법
1773정성태10/8/201430979.NET Framework: 471. 웹 브라우저로 다운로드가 되는 파일을 왜 C# 코드로 하면 안되는 걸까요? [1]
1772정성태10/3/201419786.NET Framework: 470. C# 3.0의 기본 인자(default parameter)가 .NET 1.1/2.0에서도 실행될까? [3]
1771정성태10/2/201428932개발 환경 구성: 245. 실행된 프로세스(EXE)의 명령행 인자를 확인하고 싶다면 - Sysmon [4]
1770정성태10/2/201422798개발 환경 구성: 244. 매크로 정의를 이용해 파일 하나로 C++과 C#에서 공유하는 방법 [1]파일 다운로드1
1769정성태10/1/201425539개발 환경 구성: 243. Scala 개발 환경 구성(JVM, 닷넷) [1]
1768정성태10/1/201420331개발 환경 구성: 242. 배치 파일에서 Thread.Sleep 효과를 주는 방법 [5]
1767정성태10/1/201425685VS.NET IDE: 94. Visual Studio 2012/2013에서의 매크로 구현 - Visual Commander [2]
1766정성태10/1/201423824개발 환경 구성: 241. 책 "프로그래밍 클로저: Lisp"을 읽고 나서. [1]
1765정성태9/30/201427477.NET Framework: 469. Unity3d에서 transform을 변수에 할당해 사용하는 특별한 이유가 있을까요?
1764정성태9/30/201423715오류 유형: 243. 파일 삭제가 안 되는 경우 - The action can't be comleted because the file is open in System
1763정성태9/30/201425241.NET Framework: 468. PDB 파일을 연동해 소스 코드 라인 정보를 알아내는 방법파일 다운로드1
... 121  122  123  124  125  126  127  128  129  130  131  [132]  133  134  135  ...