更改正在运行的进程的环境


18

如何在env已经运行的进程中更改某些变量,例如通过/proc/PID/environ?“ file”为read-only

需要更改或取消设置长期运行的批处理作业的DISPLAY变量,而不会终止它。


3
现在为时已晚,但为将来参考xpra可能会很有趣。
sr_

xpra听起来很有用。通常我会重新路由到由Xvfb或托管的非用户显示器Xephyr,但今天我忘记了从cli而不是cron / at运行,以对输出进行故障排除,因此在:0
Marcos 2012年

Answers:


19

没有讨厌的黑客,您就无法做到这一点-没有API,也没有办法通知进程其环境已更改(因为这实际上是不可能的)。
即使您确实做到了这一点,也无法确保它会产生任何效果-该进程很可能已经缓存了您要戳的环境变量(因为应该没有任何东西可以更改它) )。

如果您确实确实想这样做,并且准备好在出现问题的情况下继续工作,则可以使用调试器。例如,参见以下堆栈溢出问题:
是否可以更改另一个进程的环境变量?

实质上:

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

您可以尝试调用的其他可能函数是setenvunsetenv

请务必牢记,如果您所针对的过程对其环境块“感兴趣”,那么这可能不起作用或产生可怕的后果。首先要在非关键过程中进行测试,但要确保这些测试过程尽可能接近您要尝试的过程。


3
是的,我意识到这有点骇人听闻,有风险,并且由于您提到的原因而不能保证。(我访问该小组的部分原因是我似乎通常无法找到这样的非常规需求。)在这种情况下,将DISPLAY设置为垃圾或清空只会解决烦恼和延迟(网络上不必要的频繁屏幕截图,如果他们失败了)。由于子级复制父级,因此我只需要修改父级env。在我的批处理作业中,许多新的子&subchild进程正在生成并迅速退出。那些事。我想调试器可以做到这一点,谢谢-我可以将其包装到shell函数中。
马科斯(Marcos)

0

如果批处理作业可以从文件系统读取以检索更改,则无需这样做。只需运行一个具有临时唯一目录路径的作业,然后将相同路径传递给子外壳脚本即可。脚本将锁定该目录中的文件,并在锁定文件附近写入具有新值的文件。作业脚本有时会锁定相同的文件,解析并从值文件中读取更改。要查找如何在unix shell中进行锁定,只需搜索unix shell lock filebash lock file,就已经有很多解决方案。

该解决方案的优势:

  • 可在几乎任何操作系统(例如Windows或Unix)之间移植
  • 只要值文件保持简单,就不需要为每个解释器(unix / windows / etc)编写和复制复杂的解析器来从文件中读取值

实施中的问题如下:

  • 在外壳重定向阶段,实现依赖于文件锁(flock在Linux中要实现排除效果,在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

测试锁

#!/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

测试锁

@echo off

(
  pause
) 9> ./lock

以相同的方式锁定文件来写入文件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.