thay đổi môi trường của một quá trình đang chạy


18

Làm thế nào có thể thay đổi một số biến trong envquy trình đã chạy, ví dụ như thông qua /proc/PID/environ?"tệp" đó read-only.

Cần thay đổi hoặc bỏ đặt biến HIỂN THỊ của một công việc hàng loạt chạy dài mà không làm chết nó.


3
Bây giờ đã quá muộn, nhưng để tham khảo trong tương lai, xpracó thể thú vị.
sr_

xpraNghe có vẻ hữu ích. Thông thường tôi định tuyến lại đến các màn hình không sử dụng được lưu trữ bởi Xvfbhoặc Xephyr, nhưng hôm nay tôi đã quên và chạy từ cli thay vì cron / at để khắc phục sự cố đầu ra, vì vậy, điều đó làm tôi khó chịu vào lúc:0
Marcos

Câu trả lời:


19

Bạn không thể làm điều này mà không có một vụ hack khó chịu - không có API cho việc này, không có cách nào để thông báo cho quá trình rằng môi trường của nó đã thay đổi (vì dù sao điều đó không thực sự khả thi).
Ngay cả khi bạn quản lý để làm điều đó, không có cách nào để chắc chắn rằng nó sẽ có bất kỳ ảnh hưởng nào - quá trình rất có thể đã lưu trữ biến môi trường mà bạn đang cố gắng chọc (vì không có gì có thể thay đổi nó ).

Nếu bạn thực sự muốn làm điều này, và sẵn sàng nhặt các mảnh nếu gặp sự cố, bạn có thể sử dụng trình gỡ lỗi. Xem ví dụ câu hỏi Stack Overflow này:
Có cách nào để thay đổi các biến môi trường của quy trình khác không?

Bản chất:

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

Các chức năng có thể khác mà bạn có thể thử gọi là setenvhoặc unsetenv.

Xin lưu ý rằng điều này có thể không hoạt động hoặc có hậu quả nghiêm trọng nếu quy trình bạn nhắm đến thực hiện những điều "thú vị" với khối môi trường của nó. Trước tiên, hãy kiểm tra nó trên các quy trình không quan trọng, nhưng hãy đảm bảo các quy trình kiểm tra này phản ánh càng gần càng tốt với quy trình bạn đang cố gắng chọc.


3
Có, tôi nhận ra rằng đó là một phần của hack, rủi ro và không được bảo đảm vì lý do bạn đề cập. (Một phần lý do tôi truy cập nhóm này là vì những nhu cầu không thông thường như vậy mà tôi dường như không thể tìm thấy thông thường.) họ thất bại). Vì con sao chép cha mẹ, tôi chỉ cần mod cha env. Nhiều quy trình con & con mới đang được sinh ra và thoát ra nhanh chóng trong công việc hàng loạt của tôi; những vấn đề đó Tôi hình dung một trình sửa lỗi có thể làm điều này, cảm ơn - tôi có thể gói nó vào một hàm shell.
Marcos

0

Không cần phải làm như vậy nếu một công việc hàng loạt có thể đọc từ một hệ thống tệp để lấy một thay đổi. Chỉ cần chạy một công việc với đường dẫn đến một thư mục duy nhất tạm thời và chuyển cùng một đường dẫn đến tập lệnh shell con. Script sẽ khóa một tệp trong thư mục đó và viết một tệp có giá trị mới gần tệp khóa. Một tập lệnh công việc theo thời gian sẽ khóa cùng một tệp, phân tích và đọc các thay đổi trở lại từ tệp giá trị. Để tìm hiểu làm thế nào để tạo một khóa trong vỏ unix chỉ cần tìm kiếm unix shell lock filehoặc bash lock file, đã tồn tại rất nhiều giải pháp cho điều đó.

Lợi ích từ giải pháp này:

  • di động giữa hầu hết mọi hệ điều hành như Windows hoặc Unix
  • không cần phải viết và sao chép các trình phân tích cú pháp phức tạp cho mỗi trình thông dịch (unix / windows / etc) để đọc lại các giá trị từ tệp miễn là tệp giá trị vẫn đơn giản

Các vấn đề trong việc thực hiện dưới đây:

  • Việc triển khai dựa vào khóa tệp trong giai đoạn chuyển hướng hệ vỏ ( flocktrong Linux để đạt được hiệu quả loại trừ, trong Windows có loại trừ dựng sẵn)
  • Mỗi giá trị cho một biến là một giá trị dòng đơn (không phải đa dòng)

Việc triển khai được lưu trữ tại đây: https://sourceforge.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools

Việc bashthực hiện:

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"

Tương tự trên Windows (như một ví dụ về tính di động):

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

Để ghi các tập tin chỉ cần thực hiện khóa tương tự trong mã của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.