Trying to output a list of cronjobs, not a list of users. The raw output of crontab -l is way too dirty and I can't seem to clean it up. I run this with sudo script.sh or su and then run it. I've tried invoking it sudo script.sh | grep -v no also. I'm mystified why this doesn't work:
#!/bin/bash
#Trying to show all cronjobs but no extraneous info
#
# This shows "no crontab for USER" for every USER without
# a crontab - I only want to see actual cronjobs, not a long
# list of users without crontabs
echo "Here is the basic output that needs manipulation:
"
for USER in `cat /etc/passwd | cut -d":" -f1`; do
crontab -l -u $USER
done
#
# grep -v fails me
# (grep'ing the output of the script as a whole fails also)
echo "
trying with grep -v no on each line:
"
for USER in `cat /etc/passwd | cut -d":" -f1`; do
crontab -l -u $USER | grep -v no
done
echo "
maybe with quotes around the no:
"
for USER in `cat /etc/passwd | cut -d":" -f1`; do
crontab -l -u $USER | grep -v "no"
done
# string manipulation - I can't even get started
echo "
And here I try to put the commmand output into a string so I can manipulate it further, and use an if/then/fi on the product:
"
for USER in `cat /etc/passwd | cut -d":" -f1`; do
STRING="$(crontab -l -u $USER | grep -v no)"
echo "STRING: $STRING"
done
BTW, is there an easier way to get code to format correctly here than pasting in 4 spaces at the beginning of each line? I must have experimented for 40 minutes. Not complaining, just asking.
crontab is wiring the "no crontab for user" to standard error. To get rid of those messages, you can run
crontab -l -u $USER 2>/dev/null
within your loop.
I would also suggest renaming USER into something else. The USER variable name is reserved, and should be set to your user (login) name. Generally, you should use lower case variable names, to avoid this sort of name clash.
Related
For a half-finished script that already uses the output of a program I also need the name and the parameters of the program that was used to pipe to my script.
So I run it like this:
yay something | ./myscript
Now I need to store "yay something" into a variable.
There is a way to to get previous runned commands or the current one by using set -o history -o histexpand and echo !! or echo $0 but that doesn't include what I wrote right before the pipe.
Maybe you would suggest to pass the name of the program and it's parameter to my script as parameters and then run it there but I don't want this (pass a command as an argument to bash script).
UPDATED SOLUTION (old below):
#!/bin/bash -i
#get processes
processes=$(> >(ps -f))
echo beginning:
echo "$processes"
#filter bin/bash -i
pac=$(echo "$processes" | sed '1,/bin\/bash -i/!d')
pac=$(echo "$pac" | tail -2 | head -1)
#kill
delete=$(echo $pac | grep -oP "(?<=$USER\s)\w+")
pac=$(echo "$pac" | grep -o -P '(?<=00:00:00).*(?=)')
echo "$delete"
kill -9 "$delete"
#print
echo " "
echo end:
echo "${pac:1}"
Note: When you use echo, man or cat then $pac will be empty.
OLD Text:
Thanks to Charles for his enormous effort and his link that finally led me to processes=$(> >(ps -f)).
Here a working example. You can e.g. use it with vi test | ./testprocesses (or nano or package helpers like yay or trizen but it won't work with echo, man nor with cat):
#!/bin/bash -i
#get processes
processes=$(> >(ps -f))
echo beginning:
echo $processes
#filter
pac=$(echo $processes | grep -o -P '(?<=CM).*(?=testprocesses)' | grep -o -P '(?<=D).*(?=testprocesses)' | grep -o -P "(?<=00:00:00).*(?=$USER)")
#kill
delete=$(echo $pac | grep -oP "(?<=$USER\s)\w+")
pac=$(echo $pac | grep -o -P '(?<=00:00:00).*(?=)')
kill -9 $delete
#print
echo " "
echo end:
echo $pac
The kill part is necessary to kill the vi instance else it will still be running and eventually interfer with future executions of the script.
I have simple bash script, that shows information about user
#!/bin/bash
grep home /etc/passwd | grep $1
If I pass to script incorrect name, for example, ./script_find_users.sh bbbbbbbbbbbbb
the script gives nothing in output, but I want at least some simple message
echo "User does't exists"
Check the return status:
#!/bin/bash
if ! grep home /etc/passwd | grep -- "$1"; then
echo User "$1" does not have an entry in /etc/passwd >&2
fi
I have shell script i've written that deletes the oldest logfile in a directory when the mount point reaches 90% capacity. When I run the script manually it works fine but when I attempt to use crontab to run it cannot seem to execute the actual rm command but it executes everything else in the script. See my crontab and script below.
0 * * * * /acsmgmt/iselogs/iselogcleanup.sh
#!/bin/bash
df -H | grep /acsmgmt | awk '{ print $4 " " $5 }' | while read output;
do
#!echo $output
usep=$(echo $output | awk '{ print $1 }' | cut -d '%' -f1)
#!echo $usep
if [ $usep -ge 90 ]; then
echo $(date) "Logs cleaned up" >> /tmp/isecleanup.log
rm -v `ls /acsmgmt/iselogs -rt | grep "iselog-" | head -1` >> /tmp/isecleanup.log
else
echo $(date) "No logs to clean up" >> /tmp/isecleanup.log
fi
done
So, the answer is indeed, as I suspected, to always make sure you specify a correct and complete PATH variable in any script called by cron.
(I keep making this same mistake myself, even after years of writing cron scripts -- some versions of cron allow you to specify a default PATH (and other environment variables) for all your scripts, and this can help, but it also needs careful maintenance.)
I'm trying to use the script below to extract values from the df command on remote servers, then record to a log file. SSH keys are in place and no password is needed (this is not the problem).
It's getting hung up, however, and not spitting back output.
#!/bin/bash
PATH=/bin:/usr/bin:/usr/sbin
export PATH
SERVERLIST=/opt/scripts/server-list.dat
while IFS='|' read -u 3 hostname; do
echo evaluating $hostname...
SIZE=$(ssh $hostname | df -Pkhl | grep '/Volumes/UserStorage$' | awk '{print $2}')
echo $SIZE
done 3< $SERVERLIST
exit 0
You need to run df on the remote system, not pipe the output of an interactive ssh to it:
SIZE=$(ssh -n $hostname df -Pkhl | grep '/Volumes/UserStorage$' | awk '{print $2}')
Also, use the -n option to ssh to keep it from trying to read from stdin, which would consume the rest of the lines from the server list file.
Given the following 2 lines in a bash script,
LOCATION=$(curl -i -H "Windmill-Name: $APPLICATION_NAME" -H "Windmill-Identifier: $CFBundleIdentifier" -F "ipa=#$IPA" -F "plist=#$PLIST" $WINDMILL_BASE_URL/windmill/rest/windmill/$USER | grep ^Location | awk '{print $2}')
echo "[windmill] Use $LOCATION for accessing '$APPLICATION_NAME'"
In some cases, the echo string appears like below.
for accessing 'MultiPartIOSDemo'[a truncated $LOCATION]
The behaviour is not consistent but when it reproduces, the malformed output is consistent (i.e. a truncated $LOCATION at some range).
It looks like echo outputs the string to the buffer but the piping of curl isn't yet done and ends up writing its output on top.
Can't quite tell.
Update
Tried all of your suggestions, but the same problem occurs.
Have now dropped grep and the script looks like so
LOCATION=$(curl -i -H "Windmill-Name: $APPLICATION_NAME" -H "Windmill-Identifier: $CFBundleIdentifier" -F "ipa=#$IPA" -F "plist=#$PLIST" "$WINDMILL_BASE_URL/windmill/rest/windmill/$USER" | awk -W '/^Location/ {print $2}')
echo "[windmill] Use $LOCATION for accessing '$APPLICATION_NAME'"
Here are some more details.
The script that includes the above lines is wrapped in a
(
(
# bash script
) 2>&1 | tee $HOME/.windmill/$PROJECT_NAME.log
) 2>&1 | tee $HOME/.windmill/windmill.log
Hence the output of the echo is on both logs.
Just noticed that the above behaviour occurs while tailing, e.g.
tail -fn 20 ~/.windmill/windmill.log
However if I do a
more ~/.windmill/windmill.log
I can see that the echo message appears correctly. Notice the newline character "^M". Wondering if it has anything to do with the way tail parses the log.
[windmill] Use [correct $LOCATION] ^M for accessing 'MultiPartIOSDemo'
Clarified Question
Guess after all the above, there are really 2 questions.
Under what circumstances does the ^M appear in the log?
Why is tail parsing the log wrong, i.e. parsing ^M in such a way that it first outputs the "for accessing 'MultiPartIOSDemo'" then the "Use $LOCATION" on top.
I would (1) change
$WINDMILL_BASE_URL/windmill/rest/windmill/$USER
to
"$WINDMILL_BASE_URL/windmill/rest/windmill/$USER"
(2) use tee to debug
and (3) use awk to match "^location" instead of grep
LOCATION=$(curl -i -H "Windmill-Name: $APPLICATION_NAME" -H "Windmill-Identifier: $CFBundleIdentifier" -F "ipa=#$IPA" -F "plist=#$PLIST" "$WINDMILL_BASE_URL/windmill/rest/windmill/$USER" | tee /tmp/debug.$$ | awk ' /^Location/ {print $2}')
echo "[windmill] Use $LOCATION for accessing '$APPLICATION_NAME'"
Perhaps curl is returing an error. You can check the results and only parse it if no error occured
# Create a trace file
tfile=/tmp/trace.$$
# uncomment this line if you want to delete the trace file at the end of the script
#trap "/bin/rm $tfile" 0 1 15
curl -i -H "Windmill-Name: $APPLICATION_NAME" -H "Windmill-Identifier: $CFBundleIdentifier" -F "ipa=#$IPA" -F "plist=#$PLIST" "$WINDMILL_BASE_URL/windmill/rest/windmill/$USER" >$tfile
status=$?
if [ $status -eg 0 ]
then
echo curl was successful
LOCATION=$(awk '/^Location/ {print $2}' <$tfile)
echo "[windmill] Use $LOCATION for accessing '$APPLICATION_NAME'"
else
echo curl exited with status $status
fi