change environment of a running process The 2019 Stack Overflow Developer Survey Results Are InIs it possible to pass environment variables from child to parent in user space?Modify environment variable in a running processexport env variables from file in a makefileUn-mount active partitionWhy can't I print a variable I can see in the output of env?How to change DISPLAY of currently running applicationFile descriptor linked to socket or pipe in procModify environment variable in a running process“ps” output and commentshow to share environment variables between shells like globals related to a master pid?Are environment variables visible to unprivileged users on Linux?how to read any process' /proc/pid/ioWhy does a process of a binary with only execute permission remain hidden in “ps” when using hidepid=2, if the user is not root?How bash changes environmental variables on-the-fly?Why is passing the secrets via environmental variables considered “extremely insecure”?How to persist environment variables in ash, the Almquist shell?
How can I add encounters in the Lost Mine of Phandelver campaign without giving PCs too much XP?
Can a flute soloist sit?
Button changing its text & action. Good or terrible?
Why isn't the circumferential light around the M87 black hole's event horizon symmetric?
Why not take a picture of a closer black hole?
Can we generate random numbers using irrational numbers like π and e?
Loose spokes after only a few rides
Are spiders unable to hurt humans, especially very small spiders?
Why couldn't they take pictures of a closer black hole?
Mathematics of imaging the black hole
How do PCB vias affect signal quality?
Why can't devices on different VLANs, but on the same subnet, communicate?
What is the most efficient way to store a numeric range?
How to support a colleague who finds meetings extremely tiring?
Output the Arecibo Message
"as much details as you can remember"
writing variables above the numbers in tikz picture
What is this sharp, curved notch on my knife for?
How did passengers keep warm on sail ships?
How to translate "being like"?
How much of the clove should I use when using big garlic heads?
A female thief is not sold to make restitution -- so what happens instead?
For what reasons would an animal species NOT cross a *horizontal* land bridge?
Why does the nucleus not repel itself?
change environment of a running process
The 2019 Stack Overflow Developer Survey Results Are InIs it possible to pass environment variables from child to parent in user space?Modify environment variable in a running processexport env variables from file in a makefileUn-mount active partitionWhy can't I print a variable I can see in the output of env?How to change DISPLAY of currently running applicationFile descriptor linked to socket or pipe in procModify environment variable in a running process“ps” output and commentshow to share environment variables between shells like globals related to a master pid?Are environment variables visible to unprivileged users on Linux?how to read any process' /proc/pid/ioWhy does a process of a binary with only execute permission remain hidden in “ps” when using hidepid=2, if the user is not root?How bash changes environmental variables on-the-fly?Why is passing the secrets via environmental variables considered “extremely insecure”?How to persist environment variables in ash, the Almquist shell?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
How might it be possible to alter some variable in the env
of an already running process, for example through /proc/PID/environ?
That "file" is read-only
.
Need to change or unset the DISPLAY variable of a long-running batch job without killing it.
environment-variables proc
add a comment |
How might it be possible to alter some variable in the env
of an already running process, for example through /proc/PID/environ?
That "file" is read-only
.
Need to change or unset the DISPLAY variable of a long-running batch job without killing it.
environment-variables proc
3
It's too late now, but for future reference,xpra
could be interesting.
– sr_
May 9 '12 at 9:56
xpra
sounds useful. Normally I reroute to non-user displays hosted byXvfb
orXephyr
, but today I forgot and ran from cli rather than cron/at to troubleshoot output, so it's been annoying me at:0
– Marcos
May 9 '12 at 11:12
add a comment |
How might it be possible to alter some variable in the env
of an already running process, for example through /proc/PID/environ?
That "file" is read-only
.
Need to change or unset the DISPLAY variable of a long-running batch job without killing it.
environment-variables proc
How might it be possible to alter some variable in the env
of an already running process, for example through /proc/PID/environ?
That "file" is read-only
.
Need to change or unset the DISPLAY variable of a long-running batch job without killing it.
environment-variables proc
environment-variables proc
edited May 9 '12 at 9:54
Sam
1,34031628
1,34031628
asked May 9 '12 at 9:02
MarcosMarcos
1,14711228
1,14711228
3
It's too late now, but for future reference,xpra
could be interesting.
– sr_
May 9 '12 at 9:56
xpra
sounds useful. Normally I reroute to non-user displays hosted byXvfb
orXephyr
, but today I forgot and ran from cli rather than cron/at to troubleshoot output, so it's been annoying me at:0
– Marcos
May 9 '12 at 11:12
add a comment |
3
It's too late now, but for future reference,xpra
could be interesting.
– sr_
May 9 '12 at 9:56
xpra
sounds useful. Normally I reroute to non-user displays hosted byXvfb
orXephyr
, but today I forgot and ran from cli rather than cron/at to troubleshoot output, so it's been annoying me at:0
– Marcos
May 9 '12 at 11:12
3
3
It's too late now, but for future reference,
xpra
could be interesting.– sr_
May 9 '12 at 9:56
It's too late now, but for future reference,
xpra
could be interesting.– sr_
May 9 '12 at 9:56
xpra
sounds useful. Normally I reroute to non-user displays hosted by Xvfb
or Xephyr
, but today I forgot and ran from cli rather than cron/at to troubleshoot output, so it's been annoying me at :0
– Marcos
May 9 '12 at 11:12
xpra
sounds useful. Normally I reroute to non-user displays hosted by Xvfb
or Xephyr
, but today I forgot and ran from cli rather than cron/at to troubleshoot output, so it's been annoying me at :0
– Marcos
May 9 '12 at 11:12
add a comment |
2 Answers
2
active
oldest
votes
You can't do this without a nasty hacks - there's no API for this, no way to notify the process that its environment has changed (since that's not really possible anyway).
Even if you do manage to do that, there is no way to be sure that it will have any effect - the process could very well have cached the environment variable you're trying to poke (since nothing is supposed to be able to change it).
If you really do want to do this, and are prepared to pick up the pieces if things go wrong, you can use a debugger. See for instance this Stack Overflow question:
Is there a way to change another process's environment variables?
Essentially:
(gdb) attach process_id
(gdb) call putenv ("DISPLAY=your.new:value")
(gdb) detach
Other possible functions you could try to call are setenv
or unsetenv
.
Please do really keep in mind that this may not work, or have dire consequences if the process you target does "interesting" things with its environment block. Do test it out on non-critical processes first, but make sure these test processes mirror as close as possible the one you're trying to poke.
3
Yes I realize it's somewhat of a hack, risky and not guaranteed for reasons you mentioned. (Part of the reason I visit this group is for such non-conventional needs I can't seem to find ordinarily.) In this case setting DISPLAY to junk or empty merely resolves an annoyance and delay(unnecessary frequent screenshots over network,fine if they fail). Since child copies parent, I need only mod the parent env. Many new child &subchild processes are getting spawned and exit quickly in my batch job; those matter. I figured a debugger could do this, thanks--I could wrap that into a shell function.
– Marcos
May 9 '12 at 11:02
add a comment |
There is no need to do so if a batch job can read from a file system to retrieve a change. Just run a job with path to a temporary unique directory and pass the same path to the child shell script. Script will lock a file in that directory and write a file with new values near the lock file. A job script time to time will lock the same file, parse and read changes back from the values file. To find out how to make a lock in the unix shell just search for unix shell lock file
or bash lock file
, there is already exist a plenty solutions for that.
Benefits from this solution:
- portable between almost any OS like Windows or Unix
- no need to write and duplicate complex parsers for each interpreter (unix/windows/etc) to read back values from the file as long as the values file stays simple
Issues in implementation below:
- Implementation relies on a file lock in a shell redirection phase (
flock
in Linux to achieve exclusion effect, in Windows has a builtin exclusion) - Each value for a variable is a single line value (not a multiline)
Implementation is stored here: https://sourceforge.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools
The bash
implementation:
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//[$'rn']"
__VarValue="$__VarValue//[$'rn']"
# 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"
The same on Windows (as an example of portability):
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
: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 "%%j" == "%%i" echo.%%i=%%k
)
) < "%~2"
testlock.bat
@echo off
(
pause
) 9> ./lock
To write the files in just make the same way lock in your code.
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f38205%2fchange-environment-of-a-running-process%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can't do this without a nasty hacks - there's no API for this, no way to notify the process that its environment has changed (since that's not really possible anyway).
Even if you do manage to do that, there is no way to be sure that it will have any effect - the process could very well have cached the environment variable you're trying to poke (since nothing is supposed to be able to change it).
If you really do want to do this, and are prepared to pick up the pieces if things go wrong, you can use a debugger. See for instance this Stack Overflow question:
Is there a way to change another process's environment variables?
Essentially:
(gdb) attach process_id
(gdb) call putenv ("DISPLAY=your.new:value")
(gdb) detach
Other possible functions you could try to call are setenv
or unsetenv
.
Please do really keep in mind that this may not work, or have dire consequences if the process you target does "interesting" things with its environment block. Do test it out on non-critical processes first, but make sure these test processes mirror as close as possible the one you're trying to poke.
3
Yes I realize it's somewhat of a hack, risky and not guaranteed for reasons you mentioned. (Part of the reason I visit this group is for such non-conventional needs I can't seem to find ordinarily.) In this case setting DISPLAY to junk or empty merely resolves an annoyance and delay(unnecessary frequent screenshots over network,fine if they fail). Since child copies parent, I need only mod the parent env. Many new child &subchild processes are getting spawned and exit quickly in my batch job; those matter. I figured a debugger could do this, thanks--I could wrap that into a shell function.
– Marcos
May 9 '12 at 11:02
add a comment |
You can't do this without a nasty hacks - there's no API for this, no way to notify the process that its environment has changed (since that's not really possible anyway).
Even if you do manage to do that, there is no way to be sure that it will have any effect - the process could very well have cached the environment variable you're trying to poke (since nothing is supposed to be able to change it).
If you really do want to do this, and are prepared to pick up the pieces if things go wrong, you can use a debugger. See for instance this Stack Overflow question:
Is there a way to change another process's environment variables?
Essentially:
(gdb) attach process_id
(gdb) call putenv ("DISPLAY=your.new:value")
(gdb) detach
Other possible functions you could try to call are setenv
or unsetenv
.
Please do really keep in mind that this may not work, or have dire consequences if the process you target does "interesting" things with its environment block. Do test it out on non-critical processes first, but make sure these test processes mirror as close as possible the one you're trying to poke.
3
Yes I realize it's somewhat of a hack, risky and not guaranteed for reasons you mentioned. (Part of the reason I visit this group is for such non-conventional needs I can't seem to find ordinarily.) In this case setting DISPLAY to junk or empty merely resolves an annoyance and delay(unnecessary frequent screenshots over network,fine if they fail). Since child copies parent, I need only mod the parent env. Many new child &subchild processes are getting spawned and exit quickly in my batch job; those matter. I figured a debugger could do this, thanks--I could wrap that into a shell function.
– Marcos
May 9 '12 at 11:02
add a comment |
You can't do this without a nasty hacks - there's no API for this, no way to notify the process that its environment has changed (since that's not really possible anyway).
Even if you do manage to do that, there is no way to be sure that it will have any effect - the process could very well have cached the environment variable you're trying to poke (since nothing is supposed to be able to change it).
If you really do want to do this, and are prepared to pick up the pieces if things go wrong, you can use a debugger. See for instance this Stack Overflow question:
Is there a way to change another process's environment variables?
Essentially:
(gdb) attach process_id
(gdb) call putenv ("DISPLAY=your.new:value")
(gdb) detach
Other possible functions you could try to call are setenv
or unsetenv
.
Please do really keep in mind that this may not work, or have dire consequences if the process you target does "interesting" things with its environment block. Do test it out on non-critical processes first, but make sure these test processes mirror as close as possible the one you're trying to poke.
You can't do this without a nasty hacks - there's no API for this, no way to notify the process that its environment has changed (since that's not really possible anyway).
Even if you do manage to do that, there is no way to be sure that it will have any effect - the process could very well have cached the environment variable you're trying to poke (since nothing is supposed to be able to change it).
If you really do want to do this, and are prepared to pick up the pieces if things go wrong, you can use a debugger. See for instance this Stack Overflow question:
Is there a way to change another process's environment variables?
Essentially:
(gdb) attach process_id
(gdb) call putenv ("DISPLAY=your.new:value")
(gdb) detach
Other possible functions you could try to call are setenv
or unsetenv
.
Please do really keep in mind that this may not work, or have dire consequences if the process you target does "interesting" things with its environment block. Do test it out on non-critical processes first, but make sure these test processes mirror as close as possible the one you're trying to poke.
edited May 23 '17 at 12:40
Community♦
1
1
answered May 9 '12 at 10:30
MatMat
40k8123128
40k8123128
3
Yes I realize it's somewhat of a hack, risky and not guaranteed for reasons you mentioned. (Part of the reason I visit this group is for such non-conventional needs I can't seem to find ordinarily.) In this case setting DISPLAY to junk or empty merely resolves an annoyance and delay(unnecessary frequent screenshots over network,fine if they fail). Since child copies parent, I need only mod the parent env. Many new child &subchild processes are getting spawned and exit quickly in my batch job; those matter. I figured a debugger could do this, thanks--I could wrap that into a shell function.
– Marcos
May 9 '12 at 11:02
add a comment |
3
Yes I realize it's somewhat of a hack, risky and not guaranteed for reasons you mentioned. (Part of the reason I visit this group is for such non-conventional needs I can't seem to find ordinarily.) In this case setting DISPLAY to junk or empty merely resolves an annoyance and delay(unnecessary frequent screenshots over network,fine if they fail). Since child copies parent, I need only mod the parent env. Many new child &subchild processes are getting spawned and exit quickly in my batch job; those matter. I figured a debugger could do this, thanks--I could wrap that into a shell function.
– Marcos
May 9 '12 at 11:02
3
3
Yes I realize it's somewhat of a hack, risky and not guaranteed for reasons you mentioned. (Part of the reason I visit this group is for such non-conventional needs I can't seem to find ordinarily.) In this case setting DISPLAY to junk or empty merely resolves an annoyance and delay(unnecessary frequent screenshots over network,fine if they fail). Since child copies parent, I need only mod the parent env. Many new child &subchild processes are getting spawned and exit quickly in my batch job; those matter. I figured a debugger could do this, thanks--I could wrap that into a shell function.
– Marcos
May 9 '12 at 11:02
Yes I realize it's somewhat of a hack, risky and not guaranteed for reasons you mentioned. (Part of the reason I visit this group is for such non-conventional needs I can't seem to find ordinarily.) In this case setting DISPLAY to junk or empty merely resolves an annoyance and delay(unnecessary frequent screenshots over network,fine if they fail). Since child copies parent, I need only mod the parent env. Many new child &subchild processes are getting spawned and exit quickly in my batch job; those matter. I figured a debugger could do this, thanks--I could wrap that into a shell function.
– Marcos
May 9 '12 at 11:02
add a comment |
There is no need to do so if a batch job can read from a file system to retrieve a change. Just run a job with path to a temporary unique directory and pass the same path to the child shell script. Script will lock a file in that directory and write a file with new values near the lock file. A job script time to time will lock the same file, parse and read changes back from the values file. To find out how to make a lock in the unix shell just search for unix shell lock file
or bash lock file
, there is already exist a plenty solutions for that.
Benefits from this solution:
- portable between almost any OS like Windows or Unix
- no need to write and duplicate complex parsers for each interpreter (unix/windows/etc) to read back values from the file as long as the values file stays simple
Issues in implementation below:
- Implementation relies on a file lock in a shell redirection phase (
flock
in Linux to achieve exclusion effect, in Windows has a builtin exclusion) - Each value for a variable is a single line value (not a multiline)
Implementation is stored here: https://sourceforge.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools
The bash
implementation:
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//[$'rn']"
__VarValue="$__VarValue//[$'rn']"
# 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"
The same on Windows (as an example of portability):
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
: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 "%%j" == "%%i" echo.%%i=%%k
)
) < "%~2"
testlock.bat
@echo off
(
pause
) 9> ./lock
To write the files in just make the same way lock in your code.
add a comment |
There is no need to do so if a batch job can read from a file system to retrieve a change. Just run a job with path to a temporary unique directory and pass the same path to the child shell script. Script will lock a file in that directory and write a file with new values near the lock file. A job script time to time will lock the same file, parse and read changes back from the values file. To find out how to make a lock in the unix shell just search for unix shell lock file
or bash lock file
, there is already exist a plenty solutions for that.
Benefits from this solution:
- portable between almost any OS like Windows or Unix
- no need to write and duplicate complex parsers for each interpreter (unix/windows/etc) to read back values from the file as long as the values file stays simple
Issues in implementation below:
- Implementation relies on a file lock in a shell redirection phase (
flock
in Linux to achieve exclusion effect, in Windows has a builtin exclusion) - Each value for a variable is a single line value (not a multiline)
Implementation is stored here: https://sourceforge.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools
The bash
implementation:
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//[$'rn']"
__VarValue="$__VarValue//[$'rn']"
# 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"
The same on Windows (as an example of portability):
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
: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 "%%j" == "%%i" echo.%%i=%%k
)
) < "%~2"
testlock.bat
@echo off
(
pause
) 9> ./lock
To write the files in just make the same way lock in your code.
add a comment |
There is no need to do so if a batch job can read from a file system to retrieve a change. Just run a job with path to a temporary unique directory and pass the same path to the child shell script. Script will lock a file in that directory and write a file with new values near the lock file. A job script time to time will lock the same file, parse and read changes back from the values file. To find out how to make a lock in the unix shell just search for unix shell lock file
or bash lock file
, there is already exist a plenty solutions for that.
Benefits from this solution:
- portable between almost any OS like Windows or Unix
- no need to write and duplicate complex parsers for each interpreter (unix/windows/etc) to read back values from the file as long as the values file stays simple
Issues in implementation below:
- Implementation relies on a file lock in a shell redirection phase (
flock
in Linux to achieve exclusion effect, in Windows has a builtin exclusion) - Each value for a variable is a single line value (not a multiline)
Implementation is stored here: https://sourceforge.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools
The bash
implementation:
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//[$'rn']"
__VarValue="$__VarValue//[$'rn']"
# 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"
The same on Windows (as an example of portability):
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
: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 "%%j" == "%%i" echo.%%i=%%k
)
) < "%~2"
testlock.bat
@echo off
(
pause
) 9> ./lock
To write the files in just make the same way lock in your code.
There is no need to do so if a batch job can read from a file system to retrieve a change. Just run a job with path to a temporary unique directory and pass the same path to the child shell script. Script will lock a file in that directory and write a file with new values near the lock file. A job script time to time will lock the same file, parse and read changes back from the values file. To find out how to make a lock in the unix shell just search for unix shell lock file
or bash lock file
, there is already exist a plenty solutions for that.
Benefits from this solution:
- portable between almost any OS like Windows or Unix
- no need to write and duplicate complex parsers for each interpreter (unix/windows/etc) to read back values from the file as long as the values file stays simple
Issues in implementation below:
- Implementation relies on a file lock in a shell redirection phase (
flock
in Linux to achieve exclusion effect, in Windows has a builtin exclusion) - Each value for a variable is a single line value (not a multiline)
Implementation is stored here: https://sourceforge.net/p/contools/contools/HEAD/tree/trunk/Scripts/Tools
The bash
implementation:
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//[$'rn']"
__VarValue="$__VarValue//[$'rn']"
# 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"
The same on Windows (as an example of portability):
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
: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 "%%j" == "%%i" echo.%%i=%%k
)
) < "%~2"
testlock.bat
@echo off
(
pause
) 9> ./lock
To write the files in just make the same way lock in your code.
edited Apr 8 at 13:30
answered Feb 21 at 17:05
AndryAndry
1012
1012
add a comment |
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f38205%2fchange-environment-of-a-running-process%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
It's too late now, but for future reference,
xpra
could be interesting.– sr_
May 9 '12 at 9:56
xpra
sounds useful. Normally I reroute to non-user displays hosted byXvfb
orXephyr
, but today I forgot and ran from cli rather than cron/at to troubleshoot output, so it's been annoying me at:0
– Marcos
May 9 '12 at 11:12