How to `cat << 'EOF'` within `su $user <<EOF`? - bash

##!/bin/bash
set -e
backup_dir='/home/my/backup'
user='my'
su $user <<EOFHD
cat << 'EOF' > $backup_dir/autorestartnftables.sh
#!/bin/bash
SERVICENAME="nftables"
# return value is 0 if running
STATUS=$?
if [[ "$STATUS" -ne "0" ]]; then
echo "Service '$SERVICENAME' is not curently running... Starting now..."
systemctl start $SERVICENAME
fi
EOF
chmod +x $backup_dir/autorestartnftables.sh
EOFHD
Above script is used to create autorestartnftables.sh,expect result as below:
#!/bin/bash
SERVICENAME="nftables"
# return value is 0 if running
STATUS=$?
if [[ "$STATUS" -ne "0" ]]; then
echo "Service '$SERVICENAME' is not curently running... Starting now..."
systemctl start $SERVICENAME
fi
autorestartnftables.sh after run sudo bash ./example.sh:
#!/bin/bash
SERVICENAME="nftables"
# return value is 0 if running
STATUS=0
if [[ "" -ne "0" ]]; then
echo "Service '' is not curently running... Starting now..."
systemctl start
fi
Where is the problem?

Do not nest, nest, nest. Instead use declare -f and functions to transfer work to unrelated context.
##!/bin/bash
set -e
backup_dir='/home/my/backup'
user='my'
work() {
cat << 'EOF' > $backup_dir/autorestartnftables.sh
#!/bin/bash
SERVICENAME="nftables"
# return value is 0 if running
STATUS=$?
if [[ "$STATUS" -ne "0" ]]; then
echo "Service '$SERVICENAME' is not curently running... Starting now..."
systemctl start $SERVICENAME
fi
EOF
chmod +x $backup_dir/autorestartnftables.sh
}
su "$user" bash -c "$(declare -p backup_dir); $(declare -f work); work"
In this case, you could check if the user running your script is the user you want and then restart your script with that user:
##!/bin/bash
set -e
backup_dir='/home/my/backup'
user='my'
if [[ "$USER" != "$user" ]]; then
# restart yourself as that user
exec sudo -u "$user" "$0" "$#"
fi
cat << 'EOF' > $backup_dir/autorestartnftables.sh
#!/bin/bash
SERVICENAME="nftables"
# return value is 0 if running
STATUS=$?
if [[ "$STATUS" -ne "0" ]]; then
echo "Service '$SERVICENAME' is not curently running... Starting now..."
systemctl start $SERVICENAME
fi
EOF
chmod +x $backup_dir/autorestartnftables.sh
Check your scripts with shellcheck.

Related

Running 'bash -i' in re-invoked script (via sudo -S) exits immediately - why?

When I launch the following script, it restarts as root, the new bash shell opens up, but "something" sends an "exit" command immediately and the script runs to its end.
#!/bin/bash
#set -x
PASSWORD=<rootpass>
echo At start: $$
if [[ $EUID -ne 0 ]]; then
echo "No root: $$"
echo "Before sudo: $$"
sudo --remove-timestamp
echo "$PASSWORD" | sudo -S --prompt '' /bin/bash "$0" -- "$#"
echo "After sudo: $$"
#exit 0
else
echo "Root: $$"
fi
if [[ $EUID -eq 0 ]]; then
echo "Before bash: $$"
bash --rcfile <(echo "echo ; echo; echo 'Console was opened from within test.sh.'; echo In bash: $$; echo ;echo '\"exit\" to return to program.'; echo ;PS1='\[\033[01;31m\]test.sh\[\033[00m\]:\[\033[01;32m\]\u#\h\[\033[00m\]:\[\033[01;34m\]\w \$\[\033[00m\] '; pwd; cd ~; pwd;") -i
echo Bash exitcode: $?
echo "After bash: $$"
fi
BUT when I start the script in a way, that sudo has to ask for the password interactively, everything works as expected. The bash shell opens, I can do what I like, enter "exit" myself and the rest of the script is being executed.
#!/bin/bash
#set -x
echo At start: $$
if [[ $EUID -ne 0 ]]; then
echo "No root: $$"
echo "Before sudo: $$"
sudo --remove-timestamp
sudo /bin/bash "$0" -- "$#"
echo "After sudo: $$"
#exit 0
else
echo "Root: $$"
fi
if [[ $EUID -eq 0 ]]; then
echo "Before bash: $$"
bash --rcfile <(echo "echo ; echo; echo 'Console was opened from within test.sh.'; echo In bash: $$; echo ;echo '\"exit\" to return to program.'; echo ;PS1='\[\033[01;31m\]test.sh\[\033[00m\]:\[\033[01;32m\]\u#\h\[\033[00m\]:\[\033[01;34m\]\w \$\[\033[00m\] '; pwd; cd ~; pwd;") -i
echo Bash exitcode: $?
echo "After bash: $$"
fi
Can someone explain to me, why piping the password into sudo -S is behaving so differently, than a "normal" sudo call?
EDIT:
If I explicitely disable the bash internal exit command, it seems to work, but I still don't understand, where the first "exit" comes from. So this solution is more of a hack than anything else.
bash --rcfile <(echo "enable -n exit; echo; echo; echo 'Console was opened from within test.sh.'; echo In bash: $$; echo ;echo '\"exit\" to return to program.'; echo ;PS1='\[\033[01;31m\]test.sh\[\033[00m\]:\[\033[01;32m\]\u#\h\[\033[00m\]:\[\033[01;34m\]\w \$\[\033[00m\] '; pwd; cd ~; pwd;") -i
EDIT 2:
#WilliamPursell The following works now (added < /dev/ttyto bash call), but I don't know, if it has any further implications:
#!/bin/bash
#set -x
PASSWORD=<rootpass>
echo At start: $$
if [[ $EUID -ne 0 ]]; then
echo "No root: $$"
echo "Before sudo: $$"
sudo --remove-timestamp
echo "$PASSWORD" | sudo -S --prompt '' /bin/bash "$0" -- "$#"
echo "After sudo: $$"
#exit 0
else
echo "Root: $$"
fi
if [[ $EUID -eq 0 ]]; then
echo "Before bash: $$"
bash --rcfile <(echo "echo ; echo; echo 'Console was opened from within test.sh.'; echo In bash: $$; echo ;echo '\"exit\" to return to program.'; echo ;PS1='\[\033[01;31m\]test.sh\[\033[00m\]:\[\033[01;32m\]\u#\h\[\033[00m\]:\[\033[01;34m\]\w \$\[\033[00m\] '; pwd; cd ~; pwd;") -i </dev/tty
echo Bash exitcode: $?
echo "After bash: $$"
fi

Daemon script - sh: unknown operand; arithmetic syntax error

I might be blind, but I can't find the errors my script got, maybe you guys got better eyes than me :). I use a busybox compiled linux on a embedded system, Kernel 4.18.0. I found the base script here: Gist-Template
the following error is at "start":
./daemon: line 195: arithmetic syntax error
when I try "stop" these messages appear, but i dont see a unknown operand at line 0:
sh: 0: unknown operand
* Stopping Monitoring
my script:
#!/bin/sh
daemonName="Monitoring"
pidDir="."
pidFile="$pidDir/$daemonName.pid"
pidFile="$daemonName.pid"
logDir="."
# To use a dated log file.
# logFile="$logDir/$daemonName-"`date +"%Y-%m-%d"`".log"
# To use a regular log file.
logFile="$logDir/$daemonName.log"
# Log maxsize in KB
logMaxSize=1024 # 1mb
runInterval=300 # In seconds
doCommands() {
# This is where you put all the commands for the daemon.
echo "Running commands."
}
############################################################
# Below are the command functions
############################################################
hw_temp() {
cpu_temp=$(sensors|grep CPU|awk '{print $3}'|awk '{print ($0-int($0)<0.499)?int($0):int($0)+1}')
env_temp=$(sensors|grep ENV|awk '{print $3}'|awk '{print ($0-int($0)<0.499)?int($0):int($0)+1}')
pcb_temp=$(sensors|grep PCB|awk '{print $3}'|awk '{print ($0-int($0)<0.499)?int($0):int($0)+1}')
echo "$cpu_temp $env_temp $pcb_temp" >> /opt/monitoring/bla
}
############################################################
# Below is the skeleton functionality of the daemon.
############################################################
myPid=`echo $$`
setupDaemon() {
# Make sure that the directories work.
if [ ! -d "$pidDir" ]; then
mkdir "$pidDir"
fi
if [ ! -d "$logDir" ]; then
mkdir "$logDir"
fi
if [ ! -f "$logFile" ]; then
touch "$logFile"
else
# Check to see if we need to rotate the logs.
size=$((`ls -l "$logFile" | cut -d " " -f 8`/1024))
if [[ $size -gt $logMaxSize ]]; then
mv $logFile "$logFile.old"
touch "$logFile"
fi
fi
}
startDaemon() {
# Start the daemon.
setupDaemon # Make sure the directories are there.
if [[ `checkDaemon` = 1 ]]; then
echo " * \033[31;5;148mError\033[39m: $daemonName is already running."
exit 1
fi
echo " * Starting $daemonName with PID: $myPid."
echo "$myPid" > "$pidFile"
log '*** '`date +"%Y-%m-%d"`": Starting up $daemonName."
# Start the loop.
loop
}
stopDaemon() {
# Stop the daemon.
if [[ `checkDaemon` -eq 0 ]]; then
echo " * \033[31;5;148mError\033[39m: $daemonName is not running."
exit 1
fi
echo " * Stopping $daemonName"
log '*** '`date +"%Y-%m-%d"`": $daemonName stopped."
if [[ ! -z `cat $pidFile` ]]; then
kill -9 `cat "$pidFile"` &> /dev/null
fi
}
statusDaemon() {
# Query and return whether the daemon is running.
if [[ `checkDaemon` -eq 1 ]]; then
echo " * $daemonName is running."
else
echo " * $daemonName isn't running."
fi
exit 0
}
restartDaemon() {
# Restart the daemon.
if [[ `checkDaemon` = 0 ]]; then
# Can't restart it if it isn't running.
echo "$daemonName isn't running."
exit 1
fi
stopDaemon
startDaemon
}
checkDaemon() {
# Check to see if the daemon is running.
# This is a different function than statusDaemon
# so that we can use it other functions.
if [ -z "$oldPid" ]; then
return 0
elif [[ `ps aux | grep "$oldPid" | grep "$daemonName" | grep -v grep` > /dev/null ]]; then
if [ -f "$pidFile" ]; then
if [[ `cat "$pidFile"` = "$oldPid" ]]; then
# Daemon is running.
# echo 1
return 1
else
# Daemon isn't running.
return 0
fi
fi
elif [[ `ps aux | grep "$daemonName" | grep -v grep | grep -v "$myPid" | grep -v "0:00.00"` > /dev/null ]]; then
# Daemon is running but without the correct PID. Restart it.
log '*** '`date +"%Y-%m-%d"`": $daemonName running with invalid PID; restarting."
restartDaemon
return 1
else
# Daemon not running.
return 0
fi
return 1
}
loop() {
# This is the loop.
now=`date +%s`
if [ -z $last ]; then
last=`date +%s`
fi
# Do everything you need the daemon to do.
doCommands
# Check to see how long we actually need to sleep for. If we want this to run
# once a minute and it's taken more than a minute, then we should just run it
# anyway.
last=`date +%s`
# Set the sleep interval
if [[ ! $((now-last+runInterval+1)) -lt $((runInterval)) ]]; then
sleep $((now-last+runInterval))
fi
# Startover
loop
}
log() {
# Generic log function.
echo "$1" >> "$logFile"
}
###############################################################
# Parse the command.
###############################################################
if [ -f "$pidFile" ]; then
oldPid=`cat "$pidFile"`
fi
checkDaemon
case "$1" in
start)
startDaemon
;;
stop)
stopDaemon
;;
status)
statusDaemon
;;
restart)
restartDaemon
;;
*)
echo "Error: usage $0 { start | stop | restart | status }"
exit 1
esac
exit 0

How to start elasticsearch run as service in centos 7?

I have install elasticsearch 2.3.3 in centos 7 but after closing terminal elasticsearch plugin head automatically close but I want keep running in background. please give me helpful answer.
You can run it in background as two ways,
1. Nohup
2. Creating service script and put it in init.d folder
Nohup
Eg: nohup ./bin/elasticsearch
Service script
Use the following script,
#!/bin/bash
### BEGIN INIT INFO
# Provides: Elasticsearch
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Runs elasticsearch daemon
# Description: Runs the elasticsearch daemon as a non-root user
### END INIT INFO
# Process name
NAME=elasticsearch
DESC="Elasticsearch"
PROG="/etc/init.d/elasticsearch"
# Configure location of Elasticsearch bin
ELASTICSEARCH_BIN=/opt/elasticsearch-2.3.0/bin
# PID Info
PID_FOLDER=/var/run/elasticsearch/
PID_FILE=/var/run/elasticsearch/$NAME.pid
LOCK_FILE=/var/lock/subsys/$NAME
PATH=/bin:/usr/bin:/sbin:/usr/sbin:$ELASTICSEARCH_BIN
DAEMON=$ELASTICSEARCH_BIN/$NAME
# Configure logging location
ELASTICSEARCH_LOG=/var/log/elasticsearch.log
# Begin Script
RETVAL=0
if [ `id -u` -ne 0 ]; then
echo "You need root privileges to run this script"
exit 1
fi
# Function library
. /etc/init.d/functions
start() {
echo -n "Starting $DESC : "
pid=`pidofproc -p $PID_FILE elasticsearch`
if [ -n "$pid" ] ; then
echo "Already running."
exit 0
else
# Start Daemon
if [ ! -d "$PID_FOLDER" ] ; then
mkdir $PID_FOLDER
fi
daemon --user=$DAEMON_USER --pidfile=$PID_FILE $DAEMON 1>"$ELASTICSEARCH_LOG" 2>&1 &
sleep 2
pidofproc node > $PID_FILE
RETVAL=$?
[[ $? -eq 0 ]] && success || failure
echo
[ $RETVAL = 0 ] && touch $LOCK_FILE
return $RETVAL
fi
}
reload()
{
echo "Reload command is not implemented for this service."
return $RETVAL
}
stop() {
echo -n "Stopping $DESC : "
killproc -p $PID_FILE $DAEMON
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f $PID_FILE $LOCK_FILE
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status -p $PID_FILE $DAEMON
RETVAL=$?
;;
restart)
stop
start
;;
reload)
reload
;;
*)
# Invalid Arguments, print the following message.
echo "Usage: $0 {start|stop|status|restart}" >&2
exit 2
;;
esac
sudo chmod +x /etc/init.d/elasticsearch
sudo update-rc.d elasticsearch defaults 96 9
sudo /etc/init.d/elasticsearch restart

How to set exit codes for "status" command in init script for Tomcat6

I'm installing Tomcat6 and using the following for /etc/init.d/tomcat6:
#!/bin/bash
# description: Tomcat6 service
# processname: java
# chkconfig: - 99 1
## Note: CATALINA_HOME and CATALINA_PID are set elsewhere.##
# Source function library.
. /etc/init.d/functions
# Source sysconfig for tomcat6
if [ -f /etc/sysconfig/tomcat6 ]; then
. /etc/sysconfig/tomcat6
fi
[ -d "$CATALINA_HOME" ] || { echo "Tomcat requires $CATALINA_HOME."; exit 1; }
case $1 in
start|stop|run)
if su $TOMCAT_USER bash -c "cd $CATALINA_HOME/logs; $CATALINA_HOME/bin/catalina.sh $1"; then
echo -n "Tomcat $1 successful"
[ $1 == "stop" ] && rm -f $CATALINA_PID
else
echo -n "Error in Tomcat $1: $?"
fi
;;
restart)
$0 start
$0 stop
;;
status)
if [ -f "$CATALINA_PID" ]; then
read kpid < "$CATALINA_PID"
if ps --pid $kpid 2>&1 1>/dev/null; then
echo "$0 is already running at ${kpid}"
else
echo "$CATALINA_PID found, but $kpid is not running"
fi
unset kpid
else
echo "$0 is stopped"
fi
;;
esac
exit 0
The problem, as noted in this related ticket, is that Chef checks the "status" of a service and will not start it if the "status" command returns an exit code of "0". Which it always does because the script itself completes successfully, regardless of whether the service is running or not.
I need to adapt my init script to return an exit code of 3 if the service is not running, per the guidelines for Init scripts posted here:
0 program is running or service is OK
1 program is dead and /var/run pid file exists
2 program is dead and /var/lock lock file exists
3 program is not running
4 program or service status is unknown
5-99 reserved for future LSB use
100-149 reserved for distribution use
150-199 reserved for application use
200-254 reserved
I modified my initial script to:
#!/bin/bash
# description: Tomcat6 service
# processname: java
# chkconfig: - 99 1
# Source function library.
. /etc/init.d/functions
# Source sysconfig for tomcat6
if [ -f /etc/sysconfig/tomcat6 ]; then
. /etc/sysconfig/tomcat6
fi
[ -d "$CATALINA_HOME" ] || { echo "Tomcat requires $CATALINA_HOME."; exit 1; }
exit_var=0
case $1 in
start|stop|run)
if su $TOMCAT_USER bash -c "cd $CATALINA_HOME/logs; $CATALINA_HOME/bin/catalina.sh $1"; then
echo -n "Tomcat $1 successful"
[ $1 == "stop" ] && rm -f $CATALINA_PID
else
echo -n "Error in Tomcat $1: $?"
exit_var=1
fi
;;
restart)
$0 start
$0 stop
;;
status)
if [ -f "$CATALINA_PID" ]; then
read kpid < "$CATALINA_PID"
if ps --pid $kpid 2>&1 1>/dev/null; then
echo "$0 is already running at ${kpid}"
exit_var=0
else
echo "$CATALINA_PID found, but $kpid is not running"
exit_var=4
fi
unset kpid
else
echo "$0 is stopped"
exit_var=3 # Fixes issue with Chef not starting a stopped service.
fi
;;
esac
exit $exit_var
But those aren't ACTUALLY changing the exit codes for the script. How can I set different exit codes for different case scenarios?
Version Info:
OS: CentOS 6.5
Chef: 10.20
Tomcat: 6.0.39
You have the right idea, but you have exit_var=3 in the wrong place. I have placed it below to equal 3 for the status when it is already running:
status)
if [ -f "$CATALINA_PID" ]; then
read kpid < "$CATALINA_PID"
if ps --pid $kpid 2>&1 1>/dev/null; then
echo "$0 is already running at ${kpid}"
## Fixes issue with Chef not starting a stopped service.
exit_var=3 ## this is the condition of already running
else
echo "$CATALINA_PID found, but $kpid is not running"
exit_var=4
fi
unset kpid
else
echo "$0 is stopped"
exit_var=5 # (renumbered 5 set as you desire)
fi
;;
esac
exit $exit_var

How to write Gradle startup script

I have a Gradle app that I startup using ./gradlew run. This works fine, but I'm trying to deploy to an AWS instance (Ubuntu 12) and I would like the script to execute on boot. I tried writing a startup.sh file with the above command, but no dice. I've also tried adding the command to the /etc/rc.local file, but that doesn't seem to work either. Can someone give me an idea as to how to execute `./gradlew run' on startup? Thanks!
I wrote the following init script for starting gradle applications at system startup for redhat distros (centos/fedora etc).
You need to perform a few steps to tie it all together:
deploy your gradle application using gradle distZip onto your target server
create a configuration file /etc/my-service.conf
link the init script (see below) to the service name in /etc/init.d/my-service
An example configuration file /etc/my-service.conf
username=someunixuser
serviceName=MyStandaloneServer
prog="/path/to/bin/MyStandaloneServer -a any -p params -y you -w want"
javaClass="some.java.MyStandaloneServer"
Note the path to the application from the distZip in the prog line.
You then link the init script to the actual service you want it to be run as, e.g.
ln -s /path/to/gradle-init-start-stop /etc/init.d/my-service
Once you've done this, you can use chkconfig to add the service in the usual way (it defaults to 3/4/5)
Here is the script gradle-init-start-stop
#!/bin/bash
#
# chkconfig: 345 80 20
# description: Start and stop script for gradle created java application startup
#
# This is a generic file that can be used by any distribution from gradle ("gradle distZip").
# Link this file to the name of the process you want to run.
# e.g.
# ln -s /path/to/gradle-init-start-stop /etc/init.d/ivy-jetty
#
# it requires a conf file /etc/NAME.conf, e.g. /etc/ivy-jetty.conf
# otherwise it will quit.
#
# CONFIGURATION FILE ENTRIES:
# ---------------------------
# username=process-owner
# prog="/path/to/gradle-startscript -a any -e extra parameters"
# serviceName=SomeShortNameForService
# javaClass=package.for.JavaClass
. /etc/rc.d/init.d/functions
BASENAME=$(basename $0)
maxShutdownTime=15
CONF=/etc/${BASENAME}.conf
pidfile=/var/run/$BASENAME.pid
if [ ! -f $CONF ] ; then
echo "Could not find configuration file: $CONF"
exit 1
fi
####### SOURCE CONFIGURATION FILE
source $CONF
checkProcessIsRunning() {
local pid="$1"
if [ -z "$pid" -o "$pid" == " " ]; then return 1; fi
if [ ! -e /proc/$pid ]; then return 1; fi
return 0
}
checkProcessIsOurService() {
local pid="$1"
if [ "$(ps -p $pid --no-headers -o comm)" != "java" ]; then return 1; fi
grep -q --binary -F "$javaClass" /proc/$pid/cmdline
if [ $? -ne 0 ]; then return 1; fi
return 0
}
getServicePID() {
if [ ! -f $pidfile ]; then return 1; fi
pid="$(<$pidfile)"
checkProcessIsRunning $pid || return 1
checkProcessIsOurService $pid || return 1
return 0
}
startService() {
cmd="nohup $prog >/dev/null 2>&1 & echo \$!"
sudo -u $username -H $SHELL -c "$cmd" > $pidfile
sleep 0.2
pid="$(<$pidfile)"
if checkProcessIsRunning $pid; then
return 0
else
return 1
fi
}
start() {
getServicePID
if [ $? -eq 0 ]; then echo -n "$serviceName is already running"; RETVAL=0; echo ""; return 0; fi
echo -n "Starting $serviceName: "
startService
if [ $? -ne 0 ] ; then
echo "failed"
return 1
else
echo "started"
return 0
fi
}
stopService() {
# soft kill first...
kill $pid || return 1
# check if process dead, sleep 0.2s otherwise
for ((i=0; i<maxShutdownTime*5; i++)); do
checkProcessIsRunning $pid
if [ $? -ne 0 ] ; then
rm -f $pidfile
return 0
fi
sleep 0.2
done
# hard kill now...
kill -s KILL $pid || return 1
# check if process dead, sleep 0.2s otherwise
for ((i=0; i<maxShutdownTime*5; i++)); do
checkProcessIsRunning $pid
if [ $? -ne 0 ] ; then
rm -f $pidfile
return 0
fi
sleep 0.2
done
return 1
}
stop() {
getServicePID
if [ $? -ne 0 ]; then echo -n "$serviceName is not running"; RETVAL=0; echo ""; return 0; fi
pid="$(<$pidfile)"
echo -n "Stopping $serviceName "
stopService
if [ $? -ne 0 ]; then RETVAL=1; echo "failed"; return 1; fi
echo "stopped PID=$pid"
RETVAL=0
return 0
}
restart() {
stop
start
}
checkServiceStatus() {
echo -n "Checking for $serviceName: "
if getServicePID; then
echo "running PID=$pid"
RETVAL=0
else
echo "stopped"
RETVAL=3
fi
return 0;
}
####### START OF MAIN SCRIPT
RETVAL=0
case "$1" in
start)
$1
;;
stop)
$1
;;
restart)
$1
;;
status)
checkServiceStatus
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
exit 1
esac
exit $RETVAL

Resources