set env variable in bash for t seconds - bash

Is there a way to set env variable for certain number of seconds and then reset. I have a script that reads the env variable. If it is set, script should exit. Basically I am trying to build a snooze algorithm. eg. It keeps on sending messages as it receives it. However sometimes I need to snooze them for say t seconds, during these t seconds it would buffer all incoming messages and when timer t expires, send the buffer contents. My approach is to use an
if [ $MY_ENV=set ]
then
buffer
fi
However this env variable must not be shell specific. It should be for every user logged in from different locations on the same machine.

Regardless of the timing part, there's no way to set a variable in the environment of an already-running process from outside that process.
You need to use the file system for this. If it's user-specific, it can be a file in the user's home directory, for example.

If it shouldn't be shell specific, I'd use some kind of lock file for this purpose. If the lock file exists, that's the equivalent of your var being set. You can have something scheduled to delete it after t seconds.
Look at the lockfile command.

Related

bash : keeping variable for next time run of script

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.

How to export a shell variable to all sessions?

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.

how to pass information to a background process in bash

I have created a bash script and it runs in the background. It has a PID which is stored in a file, and I can use KILL to pass predefined signals to the process.
From time to time however, I'd like to pass information to the process manually. Preferably what I would like to happen is to be able to pass a string or array of information, which is captured through TRAP, then the forever loop inside the bash file will process the information. Is there an easy way to pass information into a background process?
Thanks
You can create a fifo, have the main process write to it and have the child read from it.
mkfifo link
run_sub < link &
generate_output > link
Have it listen on a socket and implement a protocol to achieve your communication aims, probably a bit much for bash.
Or, have it try to read a particular file on receipt of a particular signal. For example, it is common for programs to re-read their configuration files on receipt of a HUP.

Screen Bash Scripting for Cronjob

Hi I am trying to use screen as part of a cronjob.
Currently I have the following command:
screen -fa -d -m -S mapper /home/user/cron
Is there anyway I can make this command do nothing if the screen mapper already exists? The mapper is set on a half an hour cronjob, but sometimes the mapping takes more than half an hour to complete and so they and up overlapping, slowing each other down and sometimes even causing the next one to be slow and so I end up with lots of mapper screens running.
Thanks for your time,
ls /var/run/screen/S-"$USER"/*.mapper >/dev/null 2>&1 || screen -S mapper ...
This will check if any screen sessions named mapper exist for the current user, and only if none do, will launch the new one.
Why would you want a job run by cron, which (by definition) does not have a terminal attached to it, to do anything with the screen? According to Wikipedia, 'GNU Screen is a software application which can be used to multiplex several virtual consoles, allowing a user to access multiple separate terminal sessions'.
However, assuming there is some reason for doing it, then you probably need to create a lock file which the process checks before proceeding. At this point, you need to run a shell script from the cron entry (which is usually a good technique anyway), and the shell script can check whether the previous run of the task has completed, exiting if not. If the previous incarnation is complete, then the current incarnation creates a lock file containing its PID and runs the job. When it completes, it removes the lock file. You should review the shell trap command, and make sure that the lock file is removed if the shell script exits as a result of a trappable signal (you can't trap KILL and some process-control signals).
Judging from another answer, the screen program already creates lock files; you may not have to do anything special to create them - but will need to detect whether they exist. Also check the GNU manual for screen.

What do you do with Environment Variables?

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.

Resources