So for the life of me I cannot figure out why my script will not take my date command as a variable. I have a script that is run every time a message is received and procmail filters specific messages by their subject line. The script looks like this:
d=$(date +%Y%m%d)
:0 wc
* ^(From|subject).*xxx
| cat&>/xx/xx/xx/xx/MSG:$d && \
chmod xxx /xx/xx/xx/xx/MSG:$d && \
/xx/xx/xx/otherscript.sh /xx/xx/xx/xx/MSG:$d
I have run the date command plenty of times in other scripts and to stdout without any issue, so I am wondering if this is a procmail issue? I have looked at a few different sites about this but still have not found a solution. My end goal is to create unique file names as well as for organization purposes each time a new email comes in.
The other reason for me believing it has something to do with procmail is that it was working fine just 3 months ago (didn't change any files or permissions). I have even tried several variations (only showing a few examples):
$'date +"%Y%m%d"'
$(date)
echo $(date)
I get a variety of files created ranging with it printing MSG:(date), MSG:(date ,etc. MSG:(date appears to like it tries to read the variable but is getting cut off or the space between date and + is causing an issue.
And at the end of my script I send it to another script which also creates a new file with the date appended and it works just fine:
fileOut="/xxx/xxx/xxx/xxx.$v.$(date +"%Y%m%d-%H%M%S").xxx"
prints: xxx.YH8AcFV9.20160628-090506.txt
Thanks for your time :-)
Procmail does not support the modern POSIX shell command substitution syntax; you need to use backticks.
d=`date +%Y%m%d` # or just date +%F
If you want to avoid invoking an external process, the From_ pseudo-header contains a fresh date stamp on many architectures.
Related
My problem consists mainly of ignorance towards the different linux commands. I've run into a wall as I'm at a loss of words to correctly look up the commands I need.
However, I'd like to take the string that schemer (github.com/thefryscorer/schemer" outputs and insert it into my Terminator config at the line which starts with "palette=", replacing the existing info.
The purpose is to set this to run at intervals to keep my cycling wallpaper list updated with my bash colors.
If you could point me towards a place to learn of such automation and usage of commands, I'd be grateful.
Running Cinnamon 2.6.13 on Arch Linux, I wrote this code that, from a directory defined, takes a random file and applies it as the wallpaper. Afterwards it runs schemer and copies the newly generated config into Terminators config directory.
#!/bin/bash
#Todo;
currentmonth=August2015
#directory of wallpaper
currentfilename="$(ls ~/Pictures/wallpapers/"$currentmonth" | shuf -n 1)"
#set $currentfilename to random filename from $currentmonth
gsettings set org.cinnamon.desktop.background picture-uri file:///home/cogitantium/Pictures/wallpapers/"$currentmonth"/"$currentfilename"
#set wallpaper as current filename from default directory.
~/Go/bin/schemer -term="terminator" ~/Pictures/wallpapers/"$currentmonth"/"$currentfilename" > ~/Scripts/temp/currentpalette
#generate palette and redirect output to temporary palette file
echo "$currentmonth - $currentfilename - $currentpalette"
currentpalette="$(cat temp/currentpalette)"
#set $currentpalette to currentpalette
touch "temp/config"
sed -i "s/^.*\bpalette\b.*$/$currentpalette/g" "temp/config"
#insert generated palette into terminator config
cp "temp/config" "~/.config/terminator/config"
It does contain some errors and behaves irregularly at times. Furthermore, Terminator doesn't seem to react to the changes, even after a killall. I'll update my answer, should I find a solution.
The two things you'll need are sed and cron.
sed is a stream editor. In particular, it uses regular expressions to allow you to search through text files and replace parts of your text.
In particular, if you have
#conf.config
palette=REPLACE_ME
other.var=numbers
You can say sed s/REPLACE_ME/replaced_text/g conf.config
And sed will replace the text in conf.config with that second argument ("replace text").
So that'll be in a bash script you write.
What you'll want to do then in regularly execute your script, which you do by setting up a cron job. This will regularly execute a file.
You can either put your shell script in any one of the /etc/cron folders etc/cron.hourly, etc/cron.daily, etc, or
enter crontab -e at the terminal to open your personal cron configuration file, for more fine-grained control over when your commands execute.
The format of a cron command is as follows:
minute hour day-of-month month day-of-week command
So you could execute a command (as is explained in the sources below) once a week on Monday afternoon with
30 17 * * 1 /path/to/command (30=min, 17=5pm, and 1 is Monday as Sunday is 0-indexed).
or every 15 minutes with
*/15 * * * * /path/to/command
And your command would be ~/scripts/myscript.sh or whatever bash script has your sed command.
So you could have your cron job run schemer, then in the same script, put that string in your config file. You'll probably need to reload your config file, and the command for that (to stick at the end of your script) is source [path_to_config]
And there you go. Run schemer regularly, grab the string, stick it in your config file, and reload the file. cron, some basic bash (as I am unfamiliar with schemer, or the nature of it's output beyond "it's a string"), sed, and source.
Sources for cron jobs, as I am less familiar with them than with sed:
https://help.ubuntu.com/community/CronHowto
https://askubuntu.com/questions/2368/how-do-i-set-up-a-cron-job
How can I invoke curl command correctly from a shell script?
I have a script that actually works in one environment but doesn't on other:
I've researched a lot but still don't know what the problem is, it has to be related to fact that I'm trying to send a date time parameter that contains a space (which i have replaced by a %20). The shell runs without errors but it is not reaching the URL (I can tell that because I see no activity on the destination service)
dateTo=$(date +"%Y-%m-%d%%20%H:%M:%S")
dateFrom=$(date --date='8 hour ago' +"%Y-%m-%d%%20%H:%M:%S")
/usr/bin/curl -k "https://aurl.com/JobHandlerWeb/JobSchedulerServlet?jobId=2&busSvcId=1&receivedFromDate=$dateFrom&receivedToDate=$dateTo"
I found the issue: file format problem.
I had created the file under Windows, and that was making all the difference. Even though I thought it was the same script running fine in one environment, the file format (end line characters) were different.
Corrected using Notepadd++ --> Edit --> EOL conversion
Thanks for your help attempts
I have a script that pulls information from a file and outputs it to a different file. What i need to do is run this script everyday but output to a different file. I will have this in the crontab to run everyday at the same time but i dont know how to output to a different file everyday. Is there a loop i can use?
Regards,
John
You don't need a loop. Rather, use a stdout/stderr redirection to a filename created using 'date'
e.g.
$ myprocess.sh > `date +"%m-%d-%Y"`.log
so date is executed in the backticks (this is known as command substitution) and the output substituted in the line. Here the formatted output of date is used as the log file name (in this case 04-24-2014.log)
I need to write a Linux shell script which can scans a root directory and prints files which were modified after they were last executed.
For example, if File A executed yesterday and I modify it today, the shell script must print File A. However, if File B executed yesterday and I don't modify it yet, then file B shouldn't be printed.
Your primary problem is tracking when the files were executed.
The trouble is, Linux does not keep separate track of when a file was executed as opposed to when it was read for other purposes (such as backup, or review), so it is going to be extremely tricky to get going.
There are a variety of tricks that could be considered, but none of them are particularly trivial or inviting. One option might be to enable process accounting. Another might be to modify each script to record when it is executed.
The 'last accessed' time (or atime, or st_atime, based on the name of the field in struct stat that contains the information) doesn't help you because, as already noted, it is modified whenever the file is read. Although an executed file would certainly have been accessed, there may be many read accesses that do not execute the file but that do trigger an update of the access time.
With those caveats in place, it may be that the access time is the best that you can do, and your script needs to look for files where the access time is equal to the modify time (which means the file was modified and has not been accessed since it was modified - neither read nor printed nor executed). It is less than perfect, but it may be the best approximation available, short of a complex execution tracking system.
Once you've got a mechanism in place to track the execution times of files, then you can devise an appropriate means of working out which files were modified since they were last executed.
Unix system stores 3 time values for any file:
last access
last modification
last change.
I don't think you can get last execution time without using some artificial means, like creating a log or temp file etc. when a executable file runs.
PS: Remember not every file in Unix is an executable so that's the reason probably they never thought of storing a file's last execution timestamp as well.
However if you do want to get these time values then use:
stat -c "%X" file-name # to get last accessed time value as seconds since Epoch
stat -c "%Y" file-name # to get last modified time value as seconds since Epoch
stat -c "%Z" file-name # to get last change time value as seconds since Epoch
It is very hard to do this in shell, simply because it is very hard to get atime or mtime in a sensible format in shell. Consider moving the routine to a more full-featured language like Ruby or Perl:
ruby -e 'puts Dir["**/*"].select{ |file| File.mtime(file) > File.atime(file) }'
Use **/* for all files in current directory and below, **/*.rb for all Ruby scripts in current directory in below, /* for all files in root... you get the pattern.
Take note what I wrote in a comment to #JohanthanLeffer: UNIX does not differentiate between reading a file and executing it. Thus, printing the script out with cat ./script will have the same effect as executing it with ./script, as far as this procedure is concerned. There is no way to differentiate reading and executing that I can think of, short of making your own kernel.
However, in most cases, you probably won't read the executables; and if you edit them, the save will come after opening, so mtime will still trump atime. The only bad scenario is if you open a file in an editor then exit without saving it (or just view it with less, without modification). As long as you avoid this, the method will work.
Also make note that most editors will not actually modify a file, but create a new file and copy the contents from the old one, then overwrite the old one with the new one. This does not set the mtime, but ctime. Modify the script accordingly, if this is your usage pattern.
EDIT: Apparently, stat can help with the sensible representation. This is in bash:
#!/bin/sh
for FILE in `find .`; do
if [ `stat -f "%m -gt %a" $FILE` ]; then
echo $FILE
fi
done
Replace "find ." (with backticks) with * for just current directory, or /* for root. To use ctime instead of mtime, use %c instead of %m.
I've written a script that backs up my financial spreadsheet document to another hard drive and another computer. I have also set up my server with email to send cronjob messages to my email instead of system mail. In my script I can't figure out how to use if then to check date of backed up file and current date. Here is the script
#!/bin/bash
mount -t cifs //IP/Share /Drive/Directory -o username=username,password=password
cp /home/user/Desktop/finances10.ods /media/MediaConn/financesbackup/Daily\ Bac$
cp /home/user/Desktop/finances10.ods /Drive/Directory/FinancesBackup/Daily\ Backup/
umount /Drive/Directory
export i=`stat -c %y /media/MediaConn/financesbackup/Daily\ Backup/finances10.o$
export j=`date +%d`
if ["$i"="$j"]; then
echo Your backup has completed successfully. Please check the Daily Backup fo$
echo This message is automated by the system and mail is not checked.
else
echo Your backup has failed. Please manually backup the financial file to the$
echo drive. This message is automated by the system and mail is not checked.
fi
Pretty simple script. The output is sent by email because it's a cronjob. If anyone could help I would greatly appreciate it. Thanks in advance
Your code is all messed up in the post, but anyway... you should probably compare the output of 'stat -c %Y' (not %y) to the output of 'date +%s' (not %d).
But, even better, use something like md5sum or sha1sum to make sure the backed up file really matches the original.
I would strongly recommend checking that each command in your script has succeeded. Otherwise the script will carry on blindly and (at best) exit with a success code or (at worst) do something completely unexpected.
Here's a decent tutorial on capturing and acting on exit codes.
This line needs spaces around the brackets and equal sign:
if [ "$i" = "$j" ]; then
There's no need to export the variables in this context.
You should use the format codes that vanza suggested, since they correspond to the same format which is the number of seconds since the Unix epoch.
You should put quotes around the messages that you echo:
echo "some message"
When you pasted your code (apparently copied from nano), it got truncated. It might work better if you list it using less and copy it from there since less is likely to wrap lines rather than truncate them.
Thanks for all of the input. Sorry, I did copy and paste from nano, lol, didn't realized it was truncated. All of your advise was very helpful. I was able to do what I wanted using the format I had but just putting the spaces between the brackets and equal sign. I've never used md5sum or sha1sum but will check it out. Thanks again for all your help, it's working great now!