crontab i have the error TERM environment variable not set - bash

im using top command on shell script, when its executed on crontab i have the error TERM environment variable not set.
below my script:
#!/bin/bash
HOST=`hostname`
echo "---------------------------------------------------------------------------"
echo "Check cpu load & Memory with top on $HOST at $(date +%d/%m/%y-%H:%M:%S)"
echo "---------------------------------------------------------------------------"
echo ""
/usr/bin/top -n 1
echo ""
echo ""
echo "------check zombie process---"
/usr/bin/top -n 1 |grep zombie
echo "-----------------------------"
result after crontab script is executed
00 14 * * * /home/doug/topcommand.sh > /home/doug/check_`hostname`_`date +\%Y\%m\%d`.log 2>&1
TERM environment variable not set.
im expecting a top command result

You need to run top is batch mode for it to work in a crontab.
Use /usr/bin/top -b -n 1
It may also be useful to specify the output width you want with -w, e.g., -w 512 to get very long lines of output.
Ref: https://man7.org/linux/man-pages/man1/top.1.html

Related

Cron + nohup = script in cron cannot find command?

There is a simple cron job:
#reboot /home/user/scripts/run.sh > /dev/null 2>&1
run.sh starts a binary (simple web server):
#!/usr/bin/env bash
NPID=/home/user/server/websrv
if [ ! -f $NPID ]
then
echo "Not started"
echo "Starting"
nohup home/user/server/websrv &> my_script.out &
else
NUM=$(ps ax | grep $(cat $NPID) | grep -v grep | wc -l)
if [ $NUM -lt 1 ]
then
echo "Not working"
echo "Starting"
nohup home/user/server/websrv &> my_script.out &
else
ps ax | grep $(cat $NPID) | grep -v grep
echo "All Ok"
fi
fi
websrv gets JSON from user, and runs work.sh script itselves.
The problem is that sh script, which is invoked by websrv, "does not see" commands and stops with exit 1.
The script work.sh is like this:
#!/bin/sh -e
if [ "$#" -ne 1 ]; then
echo "Usage: $0 INPUT"
exit 1
fi
cd $(dirname $0) #good!
pwd #good!
IN="$1"
echo $IN #good!
KEYFORGIT="/some/path"
eval `ssh-agent -s` #good!
which ssh-add #good! (returns /usr/bin/ssh-add)
ssh-add $KEYFORGIT/openssh #error: exit 1!
git pull #error: exit 1!
cd $(dirname $0) #good!
rm -f somefile #error: exit 1!
#############==========Etc.==============
Usage of the full paths does not help.
If the script has been executed itself, it works.
If run.sh manually, it also works.
If I run the command nohup home/user/server/websrv & if works as well.
However, if all this chain of tools is started by cron on boot, work.sh is not able to perform any command except of cp, pwd, which, etc. But invoke of ssh-add, git, cp, rm, make etc., forces exit 1 status of the script. Why it "does not see" the commands? Unfortunately, I also cannot get any extended log which might explain the particular errors.
Try adding the path from the session that runs the script correctly to the cron entry (or inside the script)
Get the current path (where the script runs fine) with echo $PATH and add that to the crontab: replacing the string below with the output -> <REPLACE_WITH_OUTPUT_FROM_ABOVE>
#reboot export PATH=$PATH:<REPLACE_WITH_OUTPUT_FROM_ABOVE>; /home/user/scripts/run.sh > /dev/null 2>&1
You can compare paths with a cron entry like this to see what cron's PATH is:
* * * * * echo $PATH > /tmp/crons_path
Then cat /tmp/crons_path to see what it says.
Example output:
$ crontab -l | grep -v \#
* * * * * echo $PATH >> /tmp/crons_path
# wait a minute or so...
$ cat /tmp/crons_path
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$ echo $PATH
/home/ubuntu/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
As the commenter above mentioned, crontab doesn't always use the same path as user so likely something is missing.
Be sure to remove the temp cron entry after testing (crontab -e, etc.)...

OSX Command line: echo command before running it? [duplicate]

In a shell script, how do I echo all shell commands called and expand any variable names?
For example, given the following line:
ls $DIRNAME
I would like the script to run the command and display the following
ls /full/path/to/some/dir
The purpose is to save a log of all shell commands called and their arguments. Is there perhaps a better way of generating such a log?
set -x or set -o xtrace expands variables and prints a little + sign before the line.
set -v or set -o verbose does not expand the variables before printing.
Use set +x and set +v to turn off the above settings.
On the first line of the script, one can put #!/bin/sh -x (or -v) to have the same effect as set -x (or -v) later in the script.
The above also works with /bin/sh.
See the bash-hackers' wiki on set attributes, and on debugging.
$ cat shl
#!/bin/bash
DIR=/tmp/so
ls $DIR
$ bash -x shl
+ DIR=/tmp/so
+ ls /tmp/so
$
set -x will give you what you want.
Here is an example shell script to demonstrate:
#!/bin/bash
set -x #echo on
ls $PWD
This expands all variables and prints the full commands before output of the command.
Output:
+ ls /home/user/
file1.txt file2.txt
I use a function to echo and run the command:
#!/bin/bash
# Function to display commands
exe() { echo "\$ $#" ; "$#" ; }
exe echo hello world
Which outputs
$ echo hello world
hello world
For more complicated commands pipes, etc., you can use eval:
#!/bin/bash
# Function to display commands
exe() { echo "\$ ${#/eval/}" ; "$#" ; }
exe eval "echo 'Hello, World!' | cut -d ' ' -f1"
Which outputs
$ echo 'Hello, World!' | cut -d ' ' -f1
Hello
You can also toggle this for select lines in your script by wrapping them in set -x and set +x, for example,
#!/bin/bash
...
if [[ ! -e $OUT_FILE ]];
then
echo "grabbing $URL"
set -x
curl --fail --noproxy $SERV -s -S $URL -o $OUT_FILE
set +x
fi
shuckc's answer for echoing select lines has a few downsides: you end up with the following set +x command being echoed as well, and you lose the ability to test the exit code with $? since it gets overwritten by the set +x.
Another option is to run the command in a subshell:
echo "getting URL..."
( set -x ; curl -s --fail $URL -o $OUTFILE )
if [ $? -eq 0 ] ; then
echo "curl failed"
exit 1
fi
which will give you output like:
getting URL...
+ curl -s --fail http://example.com/missing -o /tmp/example
curl failed
This does incur the overhead of creating a new subshell for the command, though.
According to TLDP's Bash Guide for Beginners: Chapter 2. Writing and debugging scripts:
2.3.1. Debugging on the entire script
$ bash -x script1.sh
...
There is now a full-fledged debugger for Bash, available at SourceForge. These debugging features are available in most modern versions of Bash, starting from 3.x.
2.3.2. Debugging on part(s) of the script
set -x # Activate debugging from here
w
set +x # Stop debugging from here
...
Table 2-1. Overview of set debugging options
Short | Long notation | Result
-------+---------------+--------------------------------------------------------------
set -f | set -o noglob | Disable file name generation using metacharacters (globbing).
set -v | set -o verbose| Prints shell input lines as they are read.
set -x | set -o xtrace | Print command traces before executing command.
...
Alternatively, these modes can be specified in the script itself, by
adding the desired options to the first line shell declaration.
Options can be combined, as is usually the case with UNIX commands:
#!/bin/bash -xv
Another option is to put "-x" at the top of your script instead of on the command line:
$ cat ./server
#!/bin/bash -x
ssh user#server
$ ./server
+ ssh user#server
user#server's password: ^C
$
You can execute a Bash script in debug mode with the -x option.
This will echo all the commands.
bash -x example_script.sh
# Console output
+ cd /home/user
+ mv text.txt mytext.txt
You can also save the -x option in the script. Just specify the -x option in the shebang.
######## example_script.sh ###################
#!/bin/bash -x
cd /home/user
mv text.txt mytext.txt
##############################################
./example_script.sh
# Console output
+ cd /home/user
+ mv text.txt mytext.txt
Type "bash -x" on the command line before the name of the Bash script. For instance, to execute foo.sh, type:
bash -x foo.sh
Combining all the answers I found this to be the best, simplest
#!/bin/bash
# https://stackoverflow.com/a/64644990/8608146
exe(){
set -x
"$#"
{ set +x; } 2>/dev/null
}
# example
exe go generate ./...
{ set +x; } 2>/dev/null from https://stackoverflow.com/a/19226038/8608146
If the exit status of the command is needed, as mentioned here
Use
{ STATUS=$?; set +x; } 2>/dev/null
And use the $STATUS later like exit $STATUS at the end
A slightly more useful one
#!/bin/bash
# https://stackoverflow.com/a/64644990/8608146
_exe(){
[ $1 == on ] && { set -x; return; } 2>/dev/null
[ $1 == off ] && { set +x; return; } 2>/dev/null
echo + "$#"
"$#"
}
exe(){
{ _exe "$#"; } 2>/dev/null
}
# examples
exe on # turn on same as set -x
echo This command prints with +
echo This too prints with +
exe off # same as set +x
echo This does not
# can also be used for individual commands
exe echo what up!
For zsh, echo
setopt VERBOSE
And for debugging,
setopt XTRACE
To allow for compound commands to be echoed, I use eval plus Soth's exe function to echo and run the command. This is useful for piped commands that would otherwise only show none or just the initial part of the piped command.
Without eval:
exe() { echo "\$ $#" ; "$#" ; }
exe ls -F | grep *.txt
Outputs:
$
file.txt
With eval:
exe() { echo "\$ $#" ; "$#" ; }
exe eval 'ls -F | grep *.txt'
Which outputs
$ exe eval 'ls -F | grep *.txt'
file.txt
For csh and tcsh, you can set verbose or set echo (or you can even set both, but it may result in some duplication most of the time).
The verbose option prints pretty much the exact shell expression that you type.
The echo option is more indicative of what will be executed through spawning.
http://www.tcsh.org/tcsh.html/Special_shell_variables.html#verbose
http://www.tcsh.org/tcsh.html/Special_shell_variables.html#echo
Special shell variables
verbose
If set, causes the words of each command to be printed, after history substitution (if any). Set by the -v command line option.
echo
If set, each command with its arguments is echoed just before it is executed. For non-builtin commands all expansions occur before echoing. Builtin commands are echoed before command and filename substitution, because these substitutions are then done selectively. Set by the -x command line option.
$ cat exampleScript.sh
#!/bin/bash
name="karthik";
echo $name;
bash -x exampleScript.sh
Output is as follows:

cronjob not executing script as expected

I have this script running on a Juniper router which essentially is running Freebsd 10. Problem i am facing is the when cronjob is running this script variable ($current_mem) doesn't show any value as a result logger is also not able to log that value. Anyone have any clue what is going on.
#!/bin/bash
localpid=$$
renice -n +1 $localpid &
current_mem="test"
echo "$current_mem" <<<<shows right value
current_mem=$(cli -c "show task memory" | grep "Currently In Use" | awk
'{print $5}' | grep -o '[0-9]*')
echo "$current_mem" <<<<<<<<<<"when cron is running it show's nothing"
if [ "$current_mem" -gt "65" ]
then
echo "$current_mem" <<<<<"shows nothing"
logger -t JTASK_OS_MEM_HIGH -p "external.notice" "Using more then 65
percent of available memory Current utilization:$current_mem" <<<<<
else
echo "$current_mem"
logger -t JTASK_OS_MEM_NORMAL -p "external.notice" "Using less then 65
percent of available memory Current utilization: $current_mem"
fi
When i run this script with sh task_mem.sh, script works perfectly but when i run it through cron it doesn't show/dump the value of variable. This what i have for the cron job
# crontab -l
*/1 * * * * sh /var/tmp/task_mem.sh >>
/var/tmp/task_mem_cron.log
#GordonDavisson that was it "cli" was in /usr/sbin/cli not in /bin as a result cron was not able to execute it. Once i added the full path it started working. Thank you so much for your help

Weird output while passing parameter to script

hi i am passing parameter to my shell script and getting very weird result .Below is this script-:
#!/bin/bash
# set the STRING variable
path=$1
echo password | sudo -S -l
sudo /usr/bin/su - abcd << EOF
cd $path
#write out current crontab
crontab -l > $2
#echo new cron into cron file
echo $3
#echo $3 >> $2
#install new cron file
#crontab mycron
EOF
Above works fine, it goes on specified path,and create backup file but when it goes to echo $3 gives wrong result (weird long string i can not show here).But it only gives that output if pass parameter as belw
./createNewCron.sh /u/siebel/abcd backing.txt "00 09 * * 1-5"
But when i pass string like below it works fine-:
./createNewCron.sh /u/siebel/abcd backing.txt "echo hello"
Can anyone explain me why? Thanks
the shell expands * thus your script receives all the files in your directory. To display the stars, you need to quote echo
echo "$3"

"no space" error when using shell script with ulimit stack at 32K

The objective is to collect information about top 10 process using memory. This will help to identify the top user - over a period of time. The following script is being used. But, it stops after a period of time with "no space" error after reaching 32K limit.
#!/usr/bin/ksh
while :
do
today=`date +"%Y%m%d_%H%M%S"`
top=`svmon -P`
sum=`svmon -P -t10 -O summary=basic`
echo "$today" >> svmonps.out
echo "$top" >> svomonps.out
echo "$sum" >> svmonps.out
sleep 30
done
exit 0
Current ulimit -a setting for stack (kbytes) is 32768. Can we modify the script to continue inspite of ulimit restriction?
Thanks in advance.
You can give up using those variables & sub-shells.
run date and svmon directly to your file, or even better to the standard output, and append to svmonps.out when you call your script.
check this out:
#!/usr/bin/ksh
while :; do
date +"%Y%m%d_%H%M%S"
svmon -P
svmon -P -t10 -O summary=basic
sleep 30
done
exit 0
And when you run your script run it like this to append to your file:
$ myScript >> svmonps.out

Resources