실행중인 프로세스의 환경 변경


18

env이미 실행중인 프로세스의 일부 변수를 어떻게 변경할 수 있습니까 ( 예 /proc/PID/environ?: "file"is) read-only.

장기 실행 배치 작업의 DISPLAY 변수를 종료하지 않고 변경하거나 설정 해제해야합니다.


3
지금은 너무 늦었지만 나중에 참조하기 위해 xpra흥미로울 수 있습니다.
sr_

xpra유용하게 들립니다. 비 사용자 디스플레이에 일반적으로 I 리 라우트가 주최 Xvfb하거나 Xephyr,하지만 오늘은 그것에서 짜증나는 날이었다, 그래서 문제 해결의 출력에 /이 아니라 크론보다 CLI에서 잊고 달렸다:0
마르코스

답변:


19

불쾌한 해킹 없이이 작업을 수행 할 수 없습니다-API가 없으며 환경이 변경되었음을 프로세스에 알리는 방법이 없습니다 (어쨌든 실제로는 불가능하기 때문에).
그렇게해도 관리가 효과가 있는지 확신 할 수있는 방법은 없습니다. 프로세스는 찌르려고하는 환경 변수를 캐시 할 수 있습니다 (아무것도 바꿀 수 없기 때문에) ).

정말로 이것을하고 싶고 일이 잘못되면 조각을 집을 준비가되면 디버거를 사용할 수 있습니다. 예를 들어이 스택 오버플로 질문 :
다른 프로세스의 환경 변수를 변경하는 방법이 있습니까?

본질적으로 :

(gdb) attach process_id
(gdb) call putenv ("DISPLAY=your.new:value")
(gdb) detach

호출 할 수있는 다른 가능한 기능은 setenv또는 unsetenv입니다.

대상 프로세스가 환경 블록과 관련하여 "흥미로운"작업을 수행 할 경우 이것이 작동하지 않거나 심각한 결과를 초래할 수 있음을 명심하십시오. 중요하지 않은 프로세스에서 먼저 테스트를 수행하되, 이러한 테스트 프로세스는 찌르려고하는 프로세스와 최대한 가깝게 미러링해야합니다.


3
네, 그것은 당신이 언급 한 이유로 다소 해킹되고 위험하며 보장되지 않는다는 것을 알고 있습니다. (이 그룹을 방문한 이유 중 일부는 평범하게 찾을 수없는 비 전통적인 요구에 대한 것입니다.)이 경우 DISPLAY를 정크 또는 비우기로 설정하면 성가심과 지연이 해결됩니다 (네트워크를 통해 불필요한 스크린 샷이 자주 발생하는 경우 그들은 실패합니다). 자식은 부모를 복사하므로 부모 env 만 수정하면됩니다. 많은 새로운 하위 및 하위 프로세스가 생성되어 일괄 작업에서 빠르게 종료됩니다. 그 문제. 디버거가 이것을 할 수 있다고 생각했습니다. 감사합니다. 쉘 함수로 래핑 할 수 있습니다.
Marcos

0

배치 작업이 파일 시스템에서 변경 사항을 검색하기 위해 읽을 수있는 경우에는 그렇게 할 필요가 없습니다. 임시 고유 디렉토리에 대한 경로가있는 작업을 실행하고 동일한 경로를 하위 쉘 스크립트에 전달하십시오. 스크립트는 해당 디렉토리의 파일을 잠그고 잠금 파일 근처에 새로운 값을 가진 파일을 작성합니다. 작업 스크립트는 때때로 동일한 파일을 잠그고 값 파일에서 변경 사항을 구문 분석하고 다시 읽습니다. 유닉스 쉘에서 잠금을 만드는 방법을 찾으려면 unix shell lock file또는을 검색하면 bash lock file이미 그에 대한 많은 솔루션이 있습니다.

이 솔루션의 장점 :

  • Windows 또는 Unix와 같은 거의 모든 OS간에 이식 가능
  • value 파일이 단순하게 유지되는 한, 각 인터프리터 (unix / windows / etc)에 대해 복잡한 파서를 작성하고 복제 할 필요가 없습니다.

아래의 구현 문제 :

  • 구현은 셸 리디렉션 단계에서 파일 잠금을 사용합니다 ( flockLinux에서는 제외 효과를 달성하기 위해 Windows에는 기본적으로 제외가 있음)
  • 변수의 각 값은 단일 행 값입니다 (여러 행이 아님).

구현은 여기에 저장됩니다 : https://sourceforge.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools

그만큼 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

testlock.bat

@echo off

(
  pause
) 9> ./lock

파일을 작성하려면 동일한 방식으로 코드를 잠그십시오.

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