network manager dispatcher script fail to restart the awesome wm - linux

I want the awesome wm to run with different configuration when the network environment is changed. Therefore I wrote a script in the network manager dispatcher so that when the network environment change the script will be executed;
#!/bin/bash
# Restart awesome through awesome-client
USER=dreamingo
awesome_restart(){
/bin/su $USER -c "echo 'local awful = require (\"awful\"); return awful.util.restart()' | awesome-client"
}
#To check the cable insert or not
wire_insert_state=$(cat /sys/class/net/eth0/carrier)
#Check which config the current awesome taking(wired or wireless)
current_config=$(cat ~/.config/awesome/flag)
# if [[ $wire_insert_state = 1 ]] && [[ $current_config == "wireless" ]];then
if [[ $wire_insert_state = 1 ]];then
cp /home/dreamingo/.config/awesome/rc.lua.wire /home/dreamingo/.config/awesome/rc.lua
echo wired > ~/.config/awesome/flag
awesome_restart
# elif [[ $wire_insert_state = 0 ]] && [[ $current_config == "wired" ]];then
elif [[ $wire_insert_state = 0 ]];then
cp /home/dreamingo/.config/awesome/rc.lua.wireless /home/dreamingo/.config/awesome/rc.lua
echo wireless > ~/.config/awesome/flag
awesome_restart
fi
However, this script does run when the enviroment change, but the awesome wm won't restart.
I thought it was the reason that the script was executed by root, therefore I use the following command:
/bin/su $USER -c "echo 'local awful = require (\"awful\"); return awful.util.restart()' | awesome-client"
This command will work(restart the awesome wm) when I su to root; However, when i use:
sudo ./02check_wireless #02check_wireless was the name of the script
to run the script, the script fail to restart wm; But when i just run it as current user(dreamingo), it works;
Moreover, both the above result(success or not), the script will output:
Error org.freedesktop.DBus.Error.ServiceUnknown: The name org.naquadah.awesome.awful was not provided by any .service files
I thought the failed one also try to restart the awesome, but something covered or stop it....

This variant works fine for me with awesome 3.5.5 when I run it as root
#!/bin/bash
# Restart awesome through awesome-client
USER=my_username_here
awesome_restart(){
/bin/su $USER -c "echo 'awesome.restart()' | awesome-client"
}
awesome_restart

Related

Run script in a new screen if true

I have a script where it will check if background_logging is true, if it is then I want the rest of the script to run in a new detached screen.
I have tried using this: exec screen -dmS "alt-logging" /bin/bash "$0";. This will sometimes create the screen, etc. but other times nothing will happen at all. When it does create a screen, it doesn't run the rest of the script file and when I try to resume the screen it says it's (Dead??).
Here is the entire script, I have added some comments to explain better what I want to do:
#!/bin/bash
# Configuration files
config='config.cfg'
source "$config"
# If this is true, run the rest of the script in a new screen.
# $background_logging comes from the configuration file declared above (config).
if [ $background_logging == "true" ]; then
exec screen -dmS "alt-logging" /bin/bash "$0";
fi
[ $# -eq 0 ] && { echo -e "\nERROR: You must specify an alt file!"; exit 1; }
# Logging script
y=0
while IFS='' read -r line || [[ -n "$line" ]]; do
cmd="screen -dmS alt$y bash -c 'exec $line;'"
eval $cmd
sleep $logging_speed
y=$(( $y + 1 ))
done < "$1"
Here are the contents of the configuration file:
# This is the speed at which alts will be logged, set to 0 for fast launch.
logging_speed=5
# This is to make a new screen in which the script will run.
background_logging=true
The purpose of this script is to loop through each line in a text file and execute the line as a command. It works perfectly fine when $background_logging is false so there are no issues with the while loop.
As described, it's not entirely possible. Specifically what is going on in your script: when you exec you replace your running script code with that of screen.
What you could do though is to start screen, figure out few details about it and redirect your console scripts in/output to it, but you won't be able to reparent your running script to the screen process as if started there. Something like for instance:
#!/bin/bash
# Use a temp file to pass cat's parent pid out of screen.
tempfile=$(tempfile)
screen -dmS 'alt-logging' /bin/bash -c "echo \$\$ > \"${tempfile}\" && /bin/cat"
# Wait to receive that information on the outside (it may not be available
# immediately).
while [[ -z "${child_cat_pid}" ]] ; do
child_cat_pid=$(cat "${tempfile}")
done
# point stdin/out/err of the current shell (rest of the script) to that cat
# child process
exec 0< /proc/${child_cat_pid}/fd/0
exec 1> /proc/${child_cat_pid}/fd/1
exec 2> /proc/${child_cat_pid}/fd/2
# Rest of the script
i=0
while true ; do
echo $((i++))
sleep 1
done
Far from perfect and rather messy. It could probably be helped by using a 3rd party tool like reptyr to grab console of the script from inside the screen. But cleaner/simpler yet would be to (when desired) start the code that should be executed in that screen session after it has been established.
That said. I'd actually suggest to take a step back and ask, what exactly is it that you're trying to achieve and why exactly would you like to run your script in screen. Are you planning to attach/detach to/from it? Because if running a long term process with a detached console is what you are after, nohup might be a bit simpler route to go.

switch desktops after 5 minutes idle (xprintidle): crontab or daemon?

on my raspberry pi (raspbian running) I would like to have the current desktop switched to desktop n#0 after 5 minutes of idle system (no mouse or keyboard action), through wmctrl -s 0 and xprintidle for idle time checking.
Please keep in mind I'm no expert...
I tried 2 different ways, none of them working and I was wondering which one of them is the best way to do have the job done:
bash script and crontab
I wrote a simple script which checks if xprintidle is greater than a previously set $IDLE_TIME, than it switches desktops (saved in /usr/local/bin/switchDesktop0OnIdle):
#!/bin/bash
# 5 minutes in ms
IDLE_TIME=$((5*60*1000))
# Sequence to execute when timeout triggers.
trigger_cmd() {
wmctrl -s 0
}
sleep_time=$IDLE_TIME
triggered=false
while sleep $(((sleep_time+999)/1000)); do
idle=$(xprintidle)
if [ $idle -ge $IDLE_TIME ]; then
if ! $triggered; then
trigger_cmd
triggered=true
sleep_time=$IDLE_TIME
fi
else
triggered=false
# Give 100 ms buffer to avoid frantic loops shortly before triggers.
sleep_time=$((IDLE_TIME-idle+100))
fi
done
script itself works.
Then I added it to crontab (crontab -e) for have it run every 6 minutes
*/6 * * * * * sudo /usr/local/bin/switchDesktop0OnIdle
not sure sudo is necessary or not.
Anyway It doesn't work: googling around I understood that crontab runs in its own environment with its own variables. Even though I don't remember how to access this environment (oops) I do remember that I get these 2 errors running the script in it (which correctly works in "normal" shell)
could not open display (is it important ?)
bla bla -ge error, unary operator expected or similar: basically xprintidle doesn't work in this environment a gives back an empty value
What am I missing ?
infinite-while bash script running as daemon
second method I tried to set up a script with an internal infinite-while checking if xprintidle is greater then 5 minutes. In this case desktop is switched (less elegant?). Saved also in /usr/local/bin/switchDesktop0OnIdle
#!/bin/bash
triggered=false
while :
do
if [ `xprintidle` -ge 300000 ]; then
if [ triggered == false ]
wmctrl -s 0
triggered = true
fi
else
triggered = false
fi
fi
done
again the script itself works.
I tried to create a daemon in /etc/init.d/switchDesktop0OnIdle (really not an expert here, modified an existing one)
#! /bin/sh
# /etc/init.d/switchDesktop0OnIdle
### BEGIN INIT INFO
# Provides: switchDesktop0OnIdle
# Required-Start: $all
# Required-Stop: $all
# Should-Start:
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description:
# Description:
### END INIT INFO
DAEMON=/usr/local/bin/switchDesktop0OnIdle
NAME=switchDesktop0OnIdle
test -x $DAEMON || exit 0
case "$1" in
start)
echo -n "Starting daemon: "
start-stop-daemon --start --exec $DAEMON
echo "switchDesktop0OnIdle."
;;
stop)
echo -n "Shutting down daemon:"
start-stop-daemon --stop --oknodo --retry 30 --exec $DAEMON
echo "switchDesktop0OnIdle."
;;
restart)
echo -n "Restarting daemon: "
start-stop-daemon --stop --oknodo --retry 30 --exec $DAEMON
start-stop-daemon --start --exec $DAEMON
echo "switchDesktop0OnIdle."
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0
I set it up
sudo update-rc.d switchDesktop0OnIdle defaults
and
sudo service switchDesktop0OnIdle start
(necessary?)
...and nothing happens...
also I don't find the process with ps -ef | grep switchDesktop0OnIdle but it seems running with sudo service switchDesktop0OnIdle status
can anyone please help?
thank you
Giuseppe
As you suspected, the issue is that when you run your scripts from init or from cron, they are not running within the GUI environment you want them to control. In principle, a Linux system can have multiple X environments running. When you are using one, there are environment variables that direct the executables you are using to the environment you are in.
There are two parts to the solution: your scripts have to know which environment they are acting on, and they have to have authorization to interact with that environment.
You almost certainly are using a DISPLAY value of ":0", so export DISPLAY=:0 at the beginning of your script will handle the first part of the problem. (It might be ":0.0", which is effectively equivalent).
Authorization is a bit more complex. X can be set up to do authorization in different ways, but the most common is to have a file .Xauthority in your home directory which contains a token that is checked by the X server. If you install a script in your own crontab, it will run under your own user id (you probabl shouldn't use sudo), so it will read the right .Xauthority file. If you run from the root crontab, or from an init script, it will run as the root user, so it will have access to everything but will still need to know where to take the token from. I think that adding export XAUTHORITY=/home/joe/.Xauthority to the script will work. (Assuming your user id is joe.)

How to - multiple dropbox instances in Linux?

After looking around online it seems pretty easy to have multiple dropbox accounts running. All you have to do is change an environmental variable and then run dropbox. However, I've tried editing the .desktop file (see .desktop file specification) so the Exec line is changed from this:
Exec=dropbox start -i
which is the default, to this:
Exec=env "HOME\=/home/reg/.dropbox-alt" dropbox start -i
which from everything I have read should work. I've also tried all the variations of escaping and quoting like:
Exec=env HOME\=/home/reg/.dropbox-alt dropbox start -i
Exec=env "HOME=/home/reg/.dropbox-alt" dropbox start -i
Exec=env HOME=/home/reg/.dropbox-alt dropbox start -i
and nothing seems to launch dropbox. However if I try the same line in bash it tries to launch but falls short but that's only because dropbox is looking for a GUI. That being the case I would have thought that doing the above in the .desktop file would work but I get nothing at all happening.
I'm doing this without any dropbox instances running already so it cannot be that dropbox is looking for other instances and stopping itself from loading another instance.
If I try this in the .desktop file:
Exec=env dropbox start -i
It will launch dropbox but now it's the default instance which has no benefit.
Can anyone tell me what I'm missing to make this work?
Open a terminal and paste the following commands:
$ mkdir "$HOME"/.dropbox-alt
$ ln -s "$HOME/.Xauthority" "$HOME/.dropbox-alt/"
$ HOME="$HOME/.dropbox-alt"
$ /home/$USER/.dropbox-dist/dropboxd
Dropbox setup wizard window will appear. Finish the setup similarly as described in Method -1
start Dropbox from terminal
$ /home/$USER/.dropbox-dist/dropboxd
start Alternate-Dropbox from terminal
$ HOME="$HOME/.dropbox-alt" && /home/$USER/.dropbox-dist/dropboxd
Note:
You can create a small script with the above commands to start Dropbox.
One can put the script at startup. Don't forget to give the script execution permission.
chmod +x /path/to/script
I have tested the second method. Hope it will be useful.
#!/bin/bash
HOME_DIR=$HOME
DROPBOXES=("$HOME/.dropboxes/personal" "$HOME/.dropboxes/business")
function start_dropbox() {
HOME=$HOME_DIR
local flag
local home_dir
local OPTIND;
local verbose=0
local wait=0
while getopts p:vw opt; do
case $opt in
p) home_dir="$(echo $OPTARG | sed 's:/*$::')/" ;;
v) verbose=1 ;;
w) wait=1 ;;
*) ;;
esac
done
shift $((OPTIND-1))
# Test if the process is already running
local pid=$(ps aux|grep "${home_dir}.dropbox-dist"|grep -v 'grep'|tr -s ' '| cut -d' ' -f 2)
if [ -n "$pid" ]
then
echo "Process already running with home dir. of: $home_dir"
return 8 # Process already running
fi
# Create home directory if it doesn't exist
if [ ! -e "$home_dir" ]
then
if mkdir -p "$home_dir";
then
echo "Created directory: $home_dir"
else
echo "Failed to create directory: $home_dir"
return 9 # Failed
fi
fi
# Set up so works with GUI from command line
xauthority="${home_dir}.Xauthority"
if [ ! -e "$xauthority" ]
then
ln -s "$HOME/.Xauthority" "$xauthority"
fi
HOME="$home_dir"
# Start the dropbox daemon
if [[ $verbose -gt 0 ]]; then
echo '~/.dropbox-dist/dropboxd & '$home_dir
fi
~/.dropbox-dist/dropboxd &
if [[ $wait -eq 0 ]]; then
sleep 2 # Give each instance time to startup completely before starting another one
else
read -n 1 -s -p 'Press any key to continue.'
echo
fi
}
function start_dropboxes() {
local dropbox
for dropbox in "${DROPBOXES[#]}"
do
start_dropbox $# -p "$dropbox"
done
}
#
# For testing & setup we can choose just one to startup
#
while getopts f:wv opt; do
case $opt in
f) start_dropbox -p "${DROPBOXES[$OPTARG]}" # NOTE: bash array indexes start at 0.
exit ;;
*) ;;
esac
done
OPTIND=1
start_dropboxes $#
Not being able to install multiple instances of same software on a single machine is a typical case of what is called as Software Conflict where two such instances would compete for resources such as memory, peripheral device, register, network port, etc.
However, we could use a container-based virtualization technology called as Docker to run multiple instances of a software on the same machine in loosely isolated environments called as Containers.
The best part of this solution is that it would work on any platform, as containers are meant to portable.
I recently wrote a blog on it, explaining steps to containerise dropbox instances using docker.

How to run my looping Bash script as a service?

I have 2 Amazon Linux EC2 instances that are running HAProxy. I want to monitor each instance from the other instance and if a instance becomes unavailable, the other instance will issue a API command to move the elastic IP to the active server.
I created a Bash script to do the monitoring every XX seconds. I need to set the script to run as a service so I created a service wrapper and placed in /etc/init.d based on a template that I found and registered as a service.
The problem is when I issue command #service hamonitor start, it says "Starting hamonitor...", but I never see the OK message and if I issue the stop command, it fails and if I issue the status command, it says it is not running. But, if I check the logs, it shows that the script is in fact running. I assume that I need a proper PID file and/or since the script runs in a infinite loop, it never completes so the OK does not get issued.
Service Wrapper:
#!/bin/sh
#
# /etc/init.d/hamonitor
# Subsystem file for "hamonitor" server
#
# chkconfig: 2345 95 05 (1)
# description: hamonitor server daemon
#
# processname: hamonitor
### BEGIN INIT INFO
# Provides:
# Required-Start:
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start:
# Default-Stop:
# Short-Description:
# Description:
### END INIT INFO
# source function library
. /etc/rc.d/init.d/functions
PROG=hamonitor
EXEC=/etc/haproxy/hamonitor
LOCKFILE=/var/lock/subsys/$prog
PIDFILE=/var/run/$prog.pid
RETVAL=0
start() {
echo -n $"Starting $PROG:"
echo
#daemon $EXEC &
/etc/haproxy/hamonitor &
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
touch LOCKFILE
touch PIDFILE
echo "[ OK ]"
else
echo "[ FAIL: ${retval} ]"
fi
return $RETVAL
}
stop() {
echo -n $"Stopping $PROG:"
echo
killproc $PROG -TERM
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
rm -f LOCKFILE
rm -f PIDFILE
echo "[ OK ]"
else
echo "[ FAIL: ${RETVAL} ]"
fi
return $RETVAL
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status $PROG
RETVAL=$?
;;
restart)
stop
start
;;
*)
echo $"Usage: $0 {start|stop|status|restart}"
RETVAL=1
esac
exit $RETVAL
App:
#!/usr/bin/env bash
export EC2_HOME=/opt/aws/apitools/ec2
export JAVA_HOME=/usr/lib/jvm/jre
AWS_ACCESS_KEY="XXXXXXXXXXXXXXXXXXXXXXXXX"
AWS_SECRET_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
VIP1="1.2.3.4"
VIP1_ALLOCATIONID="eipalloc-XXXXXXX"
THIS_NODE_EC2_ID="i-XXXXXXX"
THIS_NODE_PRIVATE_IPADDRESS1="10.60.0.11"
THIS_NODE_HEALTHCHECK_URL="http://10.60.0.10/haproxy?monitor"
OTHER_NODE_HEALTHCHECK_URL="http://10.60.49.50/haproxy?monitor"
CHECK_OTHER_INTERVAL=5
CHECK_OTHER_FAIL_COUNT=0
CHECK_OTHER_RUN_COUNT=0
AFTER_TAKEOVER_WAIT=30
function takeover_vips {
/opt/aws/bin/ec2-associate-address -aws-access-key ${AWS_ACCESS_KEY} -aws-secret-key ${AWS_SECRET_KEY} -a ${VIP1_ALLOCATIONID} -i ${THIS_NODE_EC2_ID} -private-ip-address ${THIS_NODE_PRIVATE_IPADDRESS1} -allow-reassociation > /dev/null
}
function does_this_node_have_ips {
is_active=$(/opt/aws/bin/ec2-describe-addresses -aws-access-key ${AWS_ACCESS_KEY} -aws-secret-key ${AWS_SECRET_KEY} | grep ${VIP1} | grep ${THIS_NODE_EC2_ID})
if [ "$is_active" = "" ]; then
echo "no"
else
echo "yes"
fi
}
function log_msg {
msg=$1
msg="$(date) -- ${msg}"
echo ${msg} >> /var/log/hamonitorlog
}
while [ . ]; do
healthcheck_response=$(curl -sL -w "%{http_code}" ${OTHER_NODE_HEALTHCHECK_URL} -o /dev/null)
if [ "$healthcheck_response" != "200" ]; then
CHECK_OTHER_FAIL_COUNT=$((CHECK_OTHER_FAIL_COUNT+1))
if [ "$CHECK_OTHER_FAIL_COUNT" -gt 2 ]; then
takeover_vips
CHECK_OTHER_FAIL_COUNT=0
sleep ${AFTER_TAKEOVER_WAIT}
fi
sleep ${CHECK_OTHER_INTERVAL}
done
Some Linux distribution have up-start and other init; I assume you have init. The chkconfig is being used to maintain symlinks. You should confirm the comment,
# chkconfig: 2345 95 05 (1)
is correct for your system.
As a guess, you need daemon to be invoked via a script. This may have been a script function in some init script library, like /etc/rc.d/init.d/functions. I would suggest that you use the daemon() function if it exists. Either,
daemon $EXEC & #option1
nohup /etc/haproxy/hamonitor < /dev/null > /dev/null 2>&1 & #option2
/etc/haproxy/hamonitor& #option3, 2 lines.
disown $! #...
This is related to SIGCHLD and process return status (see man wait for more). As well, you may need to detach hamonitor from the controlling terminal. You can use logger to send information to the system logs in this case; I guess the App script is the hamonitor code? Just change echo to logger.
If the hamonitor needs stdout, stdin, and/or stderr, you may need to redirect to some other file if it requires it. You might also consider running it via screen if this is the case.
Edit: The last option can be used to create a proper PIDFILE. For instance,
# !!! optional grabbing of lock here...
/etc/haproxy/hamonitor & # spawn in bg
HA_PID=$! # record spawn pid
echo $HA_PID > $PIDFILE # record the PID to a file for `stop`.
# !!! optional release of lock here...
disown $HA_PID # detach script from terminal.
Services should never use echo and the like; logger is the better option. This is probably not your issue unless hamonitor tries to read from something. Mainly the issue is that start() will wait for the hamonitor to finish if you don't disown, so the rc script's start will never finish.
Generically, you can look at /etc/rc.d/init.d/functions, provide a link to your file, or provide your distribution and version (or at least linux standard base conformance which seems to define how this should work in its different versions). The file can be different on each and every Linux. You can look at this file yourself if you understand scripting to see what environment variables, files, etc are expected and what functions you use in this file. For instance, killproc is most likely defined there.

Adding a service startup script for Amazon linux AMI

I am using an Amazon Linux AMI and doing some custom modifications(added an axis2server, etc) on it and saving it as a new AMI. Now what I want to do is when the AMI boots up, start up axis2server(ie.axis2server should automatically start when the instance boots up). For that I used a init script like below and ran the following command:
chkconfig --add axisservice
But when I launch a new instance from my image, the axis2server is not getting started.
I just only need to execute the script /home/ec2-user/axis2-1.6.1/bin/axis2server.sh at startup. Am I missing anything here?
#! /bin/sh
# Basic support for IRIX style chkconfig
###
# chkconfig: 235 98 55
# description: Manages the services you are controlling with the chkconfig command
###
case "$1" in
start)
echo -n "Starting axisservice"
touch ~/temp.txt
cd /home/ec2-user/axis2-1.6.1/bin
./axis2server.sh &
echo "."
;;
stop)
echo -n "Stopping axisservice"
echo "."
;;
*)
echo "Usage: /sbin/service axisservice {start|stop}"
exit 1
esac
exit 0
I went through https://help.ubuntu.com/community/CloudInit as well and it provides a mechanism called User-Data Scripts, where a user can execute a script when launching the script.
$ euca-run-instances --key mykey --user-data-file myscript.sh ami-axxxx
This is a command line option and what I want is something like when I launch the instance through the UI, the script should be started.Therefore, I think the above option can not be used in my case. Please correct me if I am wrong.
Thanks,
H.
I bet the environment is not set(up correctly). This means that I am guessing that your shell script tries to start another program and it's not to be found.
So at first, I'd adjust the start part of your script (current):
echo -n "Starting axisservice"
touch ~/temp.txt
cd /home/ec2-user/axis2-1.6.1/bin
./axis2server.sh &
echo "."
Edited:
echo -n "Starting axisservice"
touch ~/temp.txt
cd /home/ec2-user/axis2-1.6.1/bin
./axis2server.sh
RETVAL=$?
[ $RETVAL -eq 0 ] && echo Success
[ $RETVAL -ne 0 ] && echo Failure
echo "."
So what did I do?
removed & so script waits for your shell script (axis2server.sh) to complete
checked the return status ($?) of your shell script
Further debugging:
Add set -x to your scripts to enable tracing and log both stderr and stdout.
Questions:
Are you are aware that stop (in your service script) doesn't do anything?
touch ~/temp.txt is that supposed to create /root/temp.txt? (I'm guessing root runs this script.)
If none of my suggestions work, can you share axis2server.sh and paste stderr and stdout?

Resources