I would like to know is there a way to export my shell variable to all sessions in the system (not only the current session). I'm not looking to set it in .bashrc file as the shell variable is a dynamic one it changes time to time.
You can set up your sessions to keep rereading a file on disk by setting a trap on DEBUG in your .bashrc:
trap 'source ~/.myvars' DEBUG
If you leave a terminal A open, run echo VAR=42 >> ~/.myvars in terminal B, then switch back to terminal A and echo $VAR, it'll "magically" be set.
You seem to misunderstand what export does. All it does is to move a local variable into the environment block within the process (/proc/$$/environ).
When a new process is created (a fork) then the program data areas, including the environment block, are copied to the new process (actually they are initially shared, then copied when one writes). When a different program is run (execve), by default the environment block remains from the previous program. See also the env(1) program.
So environment variables are normally inherited (copied) from their parent process. The only way to get a new environmnt variable into a running process is to use some sort of inoculation technique, as a debugger would do. Writing such a program is not an easy task, and I'm sure you could imagine the security implications.
You can't. A better explanation can be found in the unix stackexchange section here!
A shell variable probably is not suited for the use you are trying to achieve. Maybe you want to use files instead.
Related
(Please, help me adjust title and tags.)
When I run connmanctl I get a different prompt,
enrico:~$ connmanctl
connmanctl>
and different commands are available, like services, technologies, connect, ...
I'd like to know how this thing works.
I know that, in general, changing the prompt can be just a matter of changing the variable PS1. However this thing alone (read "the command connmanctl changes PS1 and returns) wouldn't have any effect at all on the functionalities of the commands line (I would still be in the same bash process).
Indeed, the fact that the available commands are changed, looks to me like the proof that connmanctl is running all the time the prompt is connmanctl>, and that, upon running connmanctl, a while loop is entered with a read statement in it, followed by a bunch of commands which process the the input.
In this latter scenario that I imagine, there's not even need to change PS1, as the connmanctl> line could simply be obtained by echo -n "connmanctl> ".
The reason behind this curiosity is that I'm trying to write a wrapper to connmanctl. I've already written it, and it works as intended, except that I don't know how to properly setup the autocompletion feature, and I think that in order to do so I first need to understand what is the right way to write an interactive shell script.
I am trying to convert some bash dotfiles to their fish equivalents.
I have a ~/.bash_logout that looks like this:
# Flush the in-memory history, then persist the emptiness to disk.
history -c && history -w;
While fish does have a history command, it does not have the same options, so the above will not work as-is in fish.
The closest I have gotten so far is history clear, though this only seems to apply to the current session and is not persisted, as the history comes back in any new tabs I create. Further, it prompts for confirmation and I would prefer not to have to do that every time I log out.
Nonetheless, it is progress, so based on another answer, I put this in ~/.config/fish/config.fish:
function on_exit --on-process %self
history clear
end
This doesn't seem to even prompt me, let alone do anything useful. Or if it does, it's non-blocking and happens so fast that I can't see it.
How can I permanently erase the fish shell history and persist that state for future sessions, within an exit handler? Existing sessions would be nice too, but are less important.
Lastly, the history manpages notes that the "builtin history" does not prompt for confirmation. Does it make sense to use that instead and if so, how?
· clear clears the history file. A prompt is displayed before the history is erased asking you to confirm you really want to clear all history unless builtin history is used.
For me, history clear seems to apply across sessions and persists through startup. Have you updated to the latest version or FiSh ? I’m using version 2.6.0.
echo $version
To remove the confirmation prompt, you can edit the function directly (funced history), removing lines 188-195 sparing 191-192. Although, all this actually does is ultimately run the command builtin history clear, so this will achieve exactly the same thing minus the confirmation. Simply type:
builtin history clear
(which, again, for me, does seem to go across sessions and is persistent.)
Regarding the event handler, the reason the exit handler doesn’t fire is because %self gets expanded into the PID of the currently running shell process. However, once that exits and a new one starts, the event handler won’t fire as the PID will be different.
So this function will fire before on exiting the currently running shell process:
function bye --on-process-exit %self
echo byeeeeeeee
end
but only that process and not any subsequently created process. Instead, add the function to your config.fish file, which will ensure it initialises the event handler each startup using the correct and current PID. The config file, if it exists, is located at ~/.config/fish/config.fish If it doesn’t exist, ensure the environment variable XDG_CONFIG_HOME is set, which tells fish where to find the config files. You can set it yourself and export it globally with:
set -gx XDG_CONFIG_HOME ~/.config/
Then create the config file with the event handler:
function bye --on-process-exit %self
builtin history clear
echo Session history scrubbed. Goodbye
end
Done. The only history item remaining will be the command exit used to end the current shell session.
Hope this helps. Seems to work for me but if you run into problems, I might be able to point you to clues for some answers.
At http://sourceforge.net/projects/auroraconkytheme/ I have this theme for conky.
One of the scripts gets a cover from the internet for the current playing song.
The script reads out the new_trackid (current song) from spotify and compares it to the first_trackid (previous song).
If they (new_trackid and first_trackid) don't match, it gets the cover of the new song aka the song has just changed.
I previously worked with writing the variables to text files.
I came across 'export' and i tried that. It seemed to work just fine by I now discovered it was comparing a number (new_trackid) with an empty variable(first_trackid).
Basically every time conky runs the scripts it forgets the variable first_trackid. Export does not work in this case.
So it keeps downloading the cover every 5 seconds (script of conky).
What am i missing?
How can i make Linux remember the variable first_trackid without using a text file next time it runs this script?
Or how to pass one variable to the same script next time it runs?
There is a lot to read about these issues. Env, source, .bashrc...
There must be a nicer way to do this.
Thanks
Ps. code pasting was unreadable
Using a file is really the right way to keep state.
The reason is that the export won't affect the environment of the parent process (your shell or cron), only itself and its children.
If running from a shell, you could source the script directly:
source ./yourscript.sh
This will evalulate it directly in your current shell, so export will effect your environment.
I have some batch files I'm trying to organize better, generally trying to get it to a spot where they might be able to be worked on a little easier by someone who comes down the road eventually.
In doing this it occurs to me that I don't know if batch scripting will persist variables in memory. Here's a example of what I have:
SET SQLSERVER="TestServer1"
SET SQLTEXT="select * from some_table"
IF NOT %SQLSERVER% = ""
CALL RUNSQL.BAT
END IF
In RUNSQL.BAT I have something similar to this:
SET SQLCMD="C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE"
%SQLCMD% -S %SQLSERVER% -Q %SQLTEXT"
EXIT
My question is: Will the variables set in that first bit of text persist into RUNSQL.BAT?
Environment variables are stored inside a block of memory in the memory space of each process. Each time a process is started, the child process gets a copy of the environment of the parent process, so at the time of start both see the same data, but don't share the same variables, child has a COPY. Any change in the environment of the parent is not seen in the environment of the child. Any change in the environment of the child is not seen in the environment of the parent.
In batch files, if both scripts are running inside the same cmd instance, both share THE SAME VARIABLES, those in the environment memory of the cmd.exe process that is running both batch files.
In the posted sample code, cmd.exe is running the first batch script, and it, inside the same cmd, calls the second batch script, that is running inside the same cmd instance, so, both are sharing the same environment variables. Second batch sees the same variables and any change made in second batch is seen in first on return of the call.
When I execute environment commands, such as env, set, and unset, something happens, but what?
set hello='hello world!'
unset find
What do you do with the commands? Are the changes permanent or temporary? Where can you see the changes? I am an Ubuntu-newbie.
The changes are temporary. They persist only in the current shell. When you set an environment variable in your ~/.profile or ~/.bash_profile (just use the one that already exists, use ls -a ~ to see), they will be effectively permanent, as these files are "sourced" every time you open up a new shell.
For instance, if you added:
export HELLO="world"
To your ~/.profile, that variable would become available every time you open a new shell (you can refresh your current shell with source ~/.profile). You could test it with:
$ echo $HELLO
world
Environment variables are used for scripts all over your system. You can do things like set your favourite editor, e.g.:
export EDITOR="nano"
One useful thing you can do is set your prompt string, e.g.:
Bill:~$ export PS1="\u is awesome$ "
Bill is awesome$ ls
Bill is awesome$ du -h
Bill is awesome$ ...etc...
Each process that is created gets its own environment which lives as long as the process. Your shell is just like any other process. Its environment is its own.
If you type 'set' with no arguments, you'll see what exists. Many of these settings are there to control program behavior.. your search path, desired X11 display, home directory (if not /home/yourname), etc.
The use is really whatever you need it to be. Any time you need to store some useful bit of information (such as long list of command line options to some program) into a variable that other applications can read, or that you can access from the shell, use the environment.
For instance:
USUAL_CONFIGURE_OPTS="--prefix=/home/charlie --sysconfdir=/home/charlie/tmp-etc"
./configure $USUAL_CONFIGURE_OPTS --and-additional-arguments
Edit:
As a programmer, I read the environment to determine the user's preferences and obey them. For instance, the variable POSIXLY_CORRECT influences the output of my programs if it is set. The environment is where the user tells programs how to behave. It also happens, the environment is a handy place for the user to store useful bits, as I described above.
Again (responding to your comment), every program that is executed is a process. A process gets its own address space (own memory), its environment is stored in that space. This means, the environment is specific to that process and lives only as long as the process itself.
Edit 2:
I think that I now fully understand your question. If someone says 'virtual environment', they are just noting that the environment resides in the application's address space, which is mapped by the kernel as virtual memory (some pages might be in physical memory, some might be in swap, shared dynamic objects, etc).
No process can access another's environment unless the process explicitly creates a map to that specific region and shares it with another process. Again, a process' address space is completely private and isolated from other processes. Environmental variables live within that address space, otherwise, the process could not access or manipulate them.
Just as with the argument list, there is a section of memory allocated for the process that stores environment variables. I believe it is a \0 separated, unsorted list of KEY=VALUE pairs.
This bit of memory is copied with every fork() and not erased by exec() so any changes are copied into child processes.
The Unix shells do not write variables into this environment variable memory until export is used. That is the difference between shell variables and environment variables.
In the bash shell, "x=2" does not set an environment variable. "export x=2" or "x=2; export x" does.