среда изменения рабочего процесса

Другой, более старый способ сделать то же самое как reset: stty sane

19
09.05.2012, 12:54
3 ответа

Вы не можете сделать этого без противные взломы - нет никакого API для этого, никакой способ уведомить процесс, что его среда изменилась (так как это не действительно возможно так или иначе).
Даже если Вам действительно удается сделать это, нет никакого способа быть уверенным, что это будет иметь любой эффект - процесс, возможно, очень хорошо кэшировал переменную среды, которую Вы пытаетесь ввести по абсолютному адресу (так как ничто, как не предполагается, может изменить его).

Если Вы действительно хотите сделать это и готовы взять части, если вещи идут не так, как надо, можно использовать отладчик. Посмотрите, например, этот вопрос о Переполнении стека:
Существует ли способ изменить переменные среды другого процесса?

По существу:

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

Другие возможные функции, которые Вы могли попытаться вызвать, setenv или unsetenv.

Действительно имейте в виду, что это не может работать, или иметь страшные последствия, если процесс, для которого Вы нацелены, делает "интересные" вещи со своим блоком среды. Действительно проверьте его на некритических процессах сначала, но удостоверьтесь эти тестовые процессы зеркало максимально близко то, которое Вы пытаетесь ввести по абсолютному адресу.

19
27.01.2020, 19:45
  • 1
    Да я понимаю, что это - своего рода взлом, опасный и не гарантируемое по причинам, которые Вы упомянули. (Часть причины, я посещаю эту группу, для таких нестандартных потребностей, которые я, может казаться, обычно не нахожу.) В этой установке DISPLAY случая, чтобы выбросить или опустеть просто разрешает раздражение и задержку (ненужные частые снимки экрана по сети, прекрасной, если они перестали работать). Так как ребенок копирует родителя, мне нужна только модификация родительский ENV. Многие новые дочерние процессы &subchild становятся порожденными и выходят быстро в моем пакетном задании; они имеют значение. Я полагал, что отладчик мог сделать это, спасибо - я мог перенести это в функцию оболочки. –  Marcos 09.05.2012, 14:02

В этом нет необходимости, если пакетное задание может считывать данные из файловой системы для извлечения изменений. Просто запустите задание с путем к временному уникальному каталогу и передайте тот же путь дочернему сценарию оболочки. Скрипт заблокирует файл в этом каталоге и запишет файл с новыми значениями рядом с файлом блокировки. Сценарий задания время от времени блокирует один и тот же файл, анализирует и считывает изменения из файла значений. Чтобы узнать, как сделать блокировку в оболочке 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/stdhttps://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/bash/tacklelib

Реализация bash:

набор _переменная _из _заблокирован _файл _пара.ш

#!/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 (как пример переносимости):

установить _переменные _из _заблокировано _файл _пара.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

Чтобы записать файлы, просто заблокируйте свой код таким же образом.

1
20.08.2021, 13:26

Если я присоединяю 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=

Я обнаружил, что putenv не работает, а setenv работает:

$] 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
7
20.08.2021, 13:26

Теги

Похожие вопросы