bash : keeping variable for next time run of script - bash

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.

Related

How to properly write an interactive shell program which can exploit bash's autocompletion mechanism

(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.

Ruby shell : how to stop a REPL copy-paste from executing?

I have some quite long script that I want users to slightly adapt to their scenario before they can copy paste in in some IRB or pry shell.
Most people would, unless paying attention, blindly copy-paste the script in some console. I'd like to stop parsing/executing the rest of the code and (for example) require a user to explicitely validate that he wants to continue running the script (for example via a simple gets that force the user to type enter)
I was thinking of something like (imagine this is the code of a wiki that one would copy paste)
# Start script
[...] # Some stuff
# Copy paste the autorization code you receive from the internet in the `token` variable
string = ("Do not blindly copy-paste, Did you do what was written in the command just above ? We need the token in the `token` variable. If you did it, just press enter. Otherwise abort with CTRL+C and restart the script".purple)
puts string
gets
Service.call(token)
The problem is that the gets/coloration seems to break further execution of the copy pasted script.
My question is, assuming you have a chunk of code that you copy paste using REPL, is there a way to abort/pause the automatic Read-Evaluate print loop via some code contained in the chunk that is copied ?
Basically I'm writing some test procedure that testers can just copy paste in their terminal to check a feature is working. 99% of the time, is is enough to just set some variables and copy-paste the code provided in the examples. But sometimes, there are some (optional) manual steps to be done in the middle of the execution of the code that is copy pasted (like copying a token, retrieving the automatically generated ID, etc.)

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.

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.

Help in understanding this bash file

I am trying to understand the code in this page: https://github.com/corroded/git-achievements/blob/gh-pages/git-achievements
and I'm kinda at a loss on how it actually works. I do know some bash and shell scripting, but how does this script actually "store" how many times you've used a command(im guessing saving into a text file?) and how does it "sense" that you actually typed in a git command? I have a feeling it's line 464 onwards that does it but I don't seem to quite follow the logic.
Can anyone explain this in a bit more understandable context?
I plan to do some achievements for other commands and I hope to have an idea on HOW to go about it without randomly copying and pasting stuff and voodoo.
Yes on 464 start the script, everything before are helping functions. I dont know how it gets installed, but I would assume you have to call this script instead of the normal git-command. It just checks if the first parameter is achievement, and if not then just (regular) git with the rest parameters is executed. Afterwards he checks if an error happend (if he exits). And then he just makes log_action and check_for_achievments. log_action just writes the issued command with a date into a text file, while achievments scans for that log file for certains events. If you want to add another achievment you have to do it in this check_for_achievments.
Just look how the big case handles it (most of the achievments call the count_function which counts the # usages of the function and matches when a power of 2 is reached).

Resources