çalışan bir sürecin ortamını değiştirme


18

envZaten çalışan bir işlemde bazı değişkenleri nasıl değiştirmek mümkün olabilir , örneğin /proc/PID/environ?O "dosya" read-only.

Uzun süredir devam eden bir toplu işin DISPLAY değişkenini öldürmeden değiştirmeniz veya ayarını kaldırmanız gerekir.


3
Şimdi çok geç, ama gelecekteki referans xpraiçin ilginç olabilir.
sr_

xprakulağa faydalı geliyor. Normalde Xvfbveya tarafından barındırılan kullanıcı olmayan ekranlara yönlendiririm Xephyr, ancak bugün çıktıyı gidermek için cron / at yerine cli'den unuttum ve koştum, bu yüzden beni rahatsız ediyor:0
Marcos

Yanıtlar:


19

Kötü bir hack olmadan bunu yapamazsınız - bunun için API yok, ortamının değiştiğini bildirmenin bir yolu yok (çünkü bu zaten mümkün değil).
Bunu yapmayı başarsanız bile, bunun herhangi bir etkisi olacağından emin olmanın bir yolu yoktur - süreç, kurcalamaya çalıştığınız ortam değişkenini çok iyi önbelleğe almış olabilir (çünkü hiçbir şeyin bunu değiştirmesi gerekmiyordu) ).

Bunu gerçekten yapmak istiyorsanız ve işler ters giderse parçaları almaya hazırsanız, bir hata ayıklayıcı kullanabilirsiniz. Örneğin şu Yığın Taşması sorusuna bakın:
Başka bir işlemin ortam değişkenlerini değiştirmenin bir yolu var mı?

esasen:

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

Aramayı deneyebileceğiniz diğer olası işlevler setenvveya unsetenv.

Lütfen bunun işe yaramayabileceğini veya hedeflediğiniz işlemin çevre bloğu ile "ilginç" şeyler yaptığında ciddi sonuçlar doğurabileceğini unutmayın. İlk olarak kritik olmayan süreçlerde test edin, ancak bu test süreçlerinin dürtmeye çalıştığınız süreci olabildiğince yakın yansıttığından emin olun.


3
Evet, bunun bir kesmek, riskli ve bahsettiğiniz nedenlerle garanti edilmediğinin farkındayım. (Bu grubu ziyaret etme nedenimin bir kısmı, normalde bulamadığım gibi geleneksel olmayan ihtiyaçlar içindir.) Bu durumda, DISPLAY'i önemsiz veya boş olarak ayarlamak yalnızca bir sıkıntı ve gecikmeyi çözer (ağ üzerinden gereksiz sık ekran görüntüleri, başarısız olurlar). Çocuk ebeveyn kopyaladığından, yalnızca ebeveyn env modunu kullanmam gerekir. Birçok yeni çocuk ve çocuk süreçleri toplu işime dönüşüyor ve hızla çıkıyor; bunlar önemli. Bir hata ayıklayıcının bunu yapabileceğini düşündüm, teşekkürler - bunu bir kabuk işlevine sarabilirim.
Marcos

0

Bir toplu iş, bir değişikliği almak için bir dosya sisteminden okuyabiliyorsa, buna gerek yoktur. Geçici bir benzersiz dizine giden yolu içeren bir işi çalıştırın ve aynı yolu alt kabuk komut dosyasına geçirin. Komut dosyası bu dizindeki bir dosyayı kilitler ve kilit dosyasının yanında yeni değerlere sahip bir dosya yazar. Bir iş komut dosyası zaman zaman aynı dosyayı kilitler, değerleri ayrıştırır ve değerleri dosyasından okur. Unix kabuğunda nasıl kilit yapılacağını öğrenmek için sadece arayın unix shell lock fileveya bash lock filebunun için bolca çözüm var.

Bu çözümün avantajları:

  • Windows veya Unix gibi neredeyse tüm işletim sistemleri arasında taşınabilir
  • değerler dosyası basit kaldığı sürece dosyadaki değerleri okumak için her yorumlayıcı (unix / windows / etc) için karmaşık ayrıştırıcılar yazıp çoğaltmaya gerek yoktur

Aşağıdaki uygulamadaki sorunlar:

  • Uygulama, kabuk yeniden yönlendirme aşamasında bir dosya kilidine dayanır ( flockdışlama efekti elde etmek için Linux'ta, Windows'da yerleşik bir dışlama vardır)
  • Bir değişken için her değer tek bir satır değeridir (çok satırlı değil)

Uygulama burada saklanır: https://sourceforge.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools

bashuygulama:

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 için de aynı şey (taşınabilirlik örneği olarak):

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

Dosyaları yazmak için kodunuzu aynı şekilde kilitleyin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.