![실행 중인 프로세스의 환경 변경](https://linux55.com/image/22956/%EC%8B%A4%ED%96%89%20%EC%A4%91%EC%9D%B8%20%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98%20%ED%99%98%EA%B2%BD%20%EB%B3%80%EA%B2%BD.png)
env
예를 들어 이미 실행 중인 프로세스에서 특정 변수를 변경하는 방법 /proc/PID/environ?
해당 "파일"은 read-only
.
장기 실행 일괄 작업을 종료하지 않고 DISPLAY 변수를 변경하거나 설정 해제해야 합니다.
답변1
불쾌한 해킹 없이는 이 작업을 수행할 수 없습니다. 이를 수행하는 API도 없고 환경이 변경되었음을 프로세스에 알릴 방법도 없습니다(어차피 실제로는 불가능하기 때문입니다).
이 작업을 수행하더라도 효과가 있다는 보장은 없습니다. 프로세스는 찌르려는 환경 변수를 이미 캐시할 가능성이 높습니다(아무 것도 변경할 수 없으므로).
정말로 이 작업을 수행하고 싶고 문제가 발생했을 때 문제를 해결할 준비가 되어 있다면 디버거를 사용할 수 있습니다. 예를 들어 다음 스택 오버플로 질문을 참조하세요.
다른 프로세스의 환경 변수를 변경하는 방법이 있습니까?
기본적으로:
(gdb) attach process_id
(gdb) call putenv ("DISPLAY=your.new:value")
(gdb) detach
호출해 볼 수 있는 다른 가능한 함수는 setenv
또는 입니다 unsetenv
.
대상 프로세스가 환경 블록에 "흥미로운" 작업을 수행하는 경우 이것이 작동하지 않거나 심각한 결과를 초래할 수 있다는 점을 기억하는 것이 중요합니다. 중요하지 않은 프로세스를 먼저 테스트하되 이러한 테스트 프로세스가 테스트하려는 프로세스와 최대한 가깝도록 하세요.
답변2
gdb를 현재 쉘에 연결하고 env 변수를 설정하려고 하면 동일하게 유지됩니다(또는 존재하지 않습니다).
$] sudo gdb -p $$
(gdb) call putenv("TEST=1234")
$1 = 0
(gdb) call (char*) getenv("TEST")
$2 = 0x0
(gdb) detach
(gdb) quit
$] echo "TEST=$TEST"
TEST=
내가 찾은푸텐프작동하지 않지만환경 변수 설정하다:
$] sudo gdb -p $$
(gdb) call (int) setenv("TEST", "1234", 1)
$1 = 0
(gdb) call (char*) getenv("TEST")
$2 = 0x55f19ff5edc0 "1234"
(gdb) detach
(gdb) quit
$] echo "TEST=$TEST"
TEST=1234
답변3
일괄 작업이 파일 시스템에서 데이터를 읽어 변경 사항을 검색할 수 있는 경우 이는 필요하지 않습니다. 임시 고유 디렉터리의 경로를 사용하여 작업을 실행하고 동일한 경로를 하위 쉘 스크립트에 전달하면 됩니다. 스크립트는 해당 디렉터리의 파일을 잠그고 잠긴 파일 근처에 새 값을 가진 파일을 작성합니다. 작업 스크립트는 때때로 동일한 파일을 잠그고 값 파일의 변경 사항을 구문 분석하고 다시 읽습니다. Unix 셸에서 잠금을 만드는 방법을 알아보려면 unix shell lock file
또는 을 검색하세요 bash lock file
. 이미 많은 솔루션이 있습니다.
이 솔루션의 이점:
- Windows 또는 Unix와 같은 거의 모든 운영 체제 간 이식 가능
- 값 파일이 단순하게 유지되는 한, 파일에서 값을 다시 읽기 위해 모든 인터프리터(unix/windows/etc)에 대해 복잡한 파서를 작성하고 복제할 필요가 없습니다.
구현상의 문제점은 다음과 같습니다.
- 쉘 리디렉션 단계에 의존하는 파일 잠금 구현(
flock
Linux에서는 제외 효과가 구현되고 Windows에서는 제외 기능이 내장되어 있음) - 변수의 각 값은 단일 행 값입니다(여러 행이 아님).
구현은 여기에 저장됩니다.https://sourceforge.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools/std https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/bash/tacklelib
구현 bash
:
set_vars_from_locked_file_pair.sh
#!/bin/bash
# Another variant of a configuration file variables read and set script.
# The script must stay as simple as possible, so for this task it uses these parameters:
# 1. path where to lock a lock file
# 2. path where to read a file with variable names (each per line)
# 3. path where to read a file with variable values (each per line, must be the same quantity of lines with the variable names file)
# Script can be ONLY included by "source" command.
if [[ -n "$BASH" && (-z "$BASH_LINENO" || ${BASH_LINENO[0]} -gt 0) ]]; then
function set_vars_from_locked_file_pair()
{
# the lock file directory must already exist
if [[ ! -d "${1%[/\\]*}" ]]; then
echo "$0: error: lock file directory does not exist: \`${1%[/\\]*}\`" >&2
return 1
fi
if [[ ! -f "${2//\\//}" ]]; then
echo "$0: error: variable names file does not exist: \`$2\`" >&2
return 2
fi
if [[ ! -f "${3//\\//}" ]]; then
echo "$0: error: variable values file does not exist: \`$3\`" >&2
return 3
fi
function LocalMain()
{
# open file for direct reading by the `read` in the same shell process
exec 7< "$2"
exec 8< "$3"
# cleanup on return
trap "rm -f \"$1\" 2> /dev/null; exec 8>&-; exec 7>&-; trap - RETURN" RETURN
local __VarName
local __VarValue
# shared acquire of the lock file
while :; do
# lock via redirection to file
{
flock -s 9
# simultaneous iteration over 2 lists in the same time
while read -r -u 7 __VarName; do
read -r -u 8 __VarValue
# drop line returns
__VarName="${__VarName//[$'\r\n']}"
__VarValue="${__VarValue//[$'\r\n']}"
# instead of `declare -gx` because `-g` is introduced only in `bash-4.2-alpha`
export $__VarName="$__VarValue"
(( ${4:-0} )) && echo "$__VarName=\`$__VarValue\`"
done
break
# return with previous code
} 9> "$1" 2> /dev/null # has exclusive lock been acquired?
# busy wait
sleep 0.02
done
}
LocalMain "${1//\\//}" "${2//\\//}" "${3//\\//}" "${4:-0}"
}
fi
testlock.sh
#!/bin/bash
{
flock -x 9 2> /dev/null
read -n1 -r -p "Press any key to continue..."
echo >&2
} 9> "lock"
Windows에서도 마찬가지입니다(이식성의 예).
set_vars_from_locked_file_pair.bat
@echo off
rem Another variant of a configuration file variables read and set script.
rem The script must stay as simple as possible, so for this task it uses these parameters:
rem 1. path where to lock a lock file
rem 2. path where to read a file with variable names (each per line)
rem 3. path where to read a file with variable values (each per line, must be the same quantity of lines with the variable names file)
rem disable alternative variables expansion to avoid `!` character consumption
setlocal DISABLEDELAYEDEXPANSION
set "FILE_LOCK_PATH=%~1"
set "FILE_VAR_NAMES_PATH=%~2"
set "FILE_VAR_VALUES_PATH=%~3"
set "PRINT_VARS_SET=%~4"
set "FILE_LOCK_DIR=%~d1"
rem the lock file directory must already exist
if not exist "%FILE_LOCK_DIR%" (
echo.%~nx0: error: FILE_LOCK_DIR does not exist: "%FILE_LOCK_DIR%"
exit /b 1
) >&2
if not exist "%FILE_VAR_NAMES_PATH%" (
echo.%~nx0: error: FILE_VAR_NAMES_PATH does not exist: "%FILE_VAR_NAMES_PATH%"
exit /b 2
) >&2
if not exist "%FILE_VAR_VALUES_PATH%" (
echo.%~nx0: error: FILE_VAR_VALUES_PATH does not exist: "%FILE_VAR_VALUES_PATH%"
exit /b 3
) >&2
rem The endlocal works only in the same call context
endlocal
rem exclusive acquire of the lock file
:REPEAT_LOCK_LOOP
(
(
rem if lock is acquired, then we are in...
call :MAIN "%%~2" "%%~3" "%%~4"
call set "LASTERROR=%%ERRORLEVEL%%"
rem exit with return code from the MAIN
) 9> "%~1" && (del /F /Q /A:-D "%~1" & goto EXIT)
) 2>nul
rem Busy wait: with external call significantly reduces CPU consumption while in a waiting state
pathping localhost -n -q 1 -p 20 >nul 2>&1
goto REPEAT_LOCK_LOOP
:EXIT
exit /b %LASTERROR%
:MAIN
rem drop last error
type nul>nul
if %~30 NEQ 0 goto SET_WITH_PRINT
rem trick with simultaneous iteration over 2 lists in the same time
(
for /f "usebackq eol=# tokens=* delims=" %%i in ("%~1") do (
set /p "%%i="
)
) < "%~2"
exit /b 0
:SET_WITH_PRINT
rem trick with simultaneous iteration over 2 lists in the same time
(
for /f "usebackq eol=# tokens=* delims=" %%i in ("%~1") do (
set /p "%%i="
rem to filter out wrong matches of a variable from the `set "%%i"`
for /f "usebackq eol=# tokens=1,* delims==" %%j in (`set "%%i"`) do if /i "%%j" == "%%i" echo.%%i=%%k
)
) < "%~2"
exit /b 0
테스트 lock.bat
@echo off
(
pause
) 9> ./lock
파일에 쓰려면 같은 방식으로 코드를 잠그면 됩니다.