monit: use hostname in logfile path - monit

I am new to monit and want to use different logfile path for monit (not the default one)
set logfile /x/home/xxxx/yyyy/monit/monit-5.20.0/logs/monit_$HOST.log
In place of $HOST, I want the hostname where the monit is running.
Any idea how can we achieve this? Similarly, I wan to use the hostname for idfile and statefile as well.
Note: /x/home/xxxx/yyyy/monit/monit-5.20.0 is common mount for all machines and want to run monit on them. But don't want the same log file.

Finally I found the way to have hostname in the logfile, idfile and statsfile.
I created a wrapper script start.sh as follows and started the monit by passing control file, logfile, idfile and statsfile.
#!/bin/bash
BASEDIR=`dirname $0`
HOST=`hostname`
MONIT_BIN=$BASEDIR/bin/monit
CTRL_FILE=$BASEDIR/conf/monitrc
LOG_FILE=$BASEDIR/logs/monit_$HOST.log
PID_FILE=$BASEDIR/run/monit_$HOST.pid
STATS_FILE=$BASEDIR/run/.monit_$HOST.state
mkdir -p $BASEDIR/run
mkdir -p $BASEDIR/logs
touch $PID_FILE
touch $STATS_FILE
touch $LOG_FILE
nohup $MONIT_BIN -c $CTRL_FILE -l $LOG_FILE -p $PID_FILE -s $STATS_FILE &> /dev/null &

Related

Why do I have to spawn a new shell when doing remote sudo ssh commands to get proper file permissions?

I'm using password-less key based login with sudo to execute remote commands. I have figured out that I have to spawn a new shell to execute commands that write to root areas of the remote file system. But, I would like a clear explanation of exactly why this is the case?
This fails:
sudo -u joe ssh example.com "sudo echo test > /root/echo_test"
with:
bash: /root/echo_test: Permission denied
This works fine:
sudo -u joe ssh example.com "sudo bash -c 'echo test > /root/echo_test'"
It's the same reason that a local sudo echo test >/root/echo_test will fail (if you are not root) -- the redirection is done by the shell (not the sudo or echo command) which is running as the normal user. sudo only runs the echo command as root.
With sudo -u joe ssh example.com "sudo echo test > /root/echo_test", the remote shell is running as a normal user (probably joe) and does not have permission to write to the file. Using an extra bash invokation works, because sudo then runs bash as root (rather than echo), and that bash can open the file and do the redirect.

How to automatically start tmux on SSH session?

I have ten or so servers that I connect to with SSH on a regular basis. Each has an entry in my local computer's ~/.ssh/config file.
To avoid losing control of my running process when my Internet connection inevitably drops, I always work inside a tmux session. I would like a way to have tmux automatically connect every time an SSH connection is started, so I don't have to always type tmux attach || tmux new after I SSH in.
Unfortunately this isn't turning out to be as simple as I originally hoped.
I don't want to add any commands to the ~/.bashrc on the servers because I only want it for SSH sessions, not local sessions.
Adding tmux attach || tmux new to the ~/.ssh/rc on the servers simply results in the error not a terminal being thrown after connection, even when the RequestTTY force option is added to the line for that server in my local SSH config file.
Server-side configuration:
To automatically start tmux on your remote server when ordinarily logging in via SSH (and only SSH), edit the ~/.bashrc of your user or root (or both) on the remote server accordingly:
if [[ $- =~ i ]] && [[ -z "$TMUX" ]] && [[ -n "$SSH_TTY" ]]; then
tmux attach-session -t ssh_tmux || tmux new-session -s ssh_tmux
fi
This command creates a tmux session called ssh_tmux if none exists, or reattaches to a already existing session with that name. In case your connection dropped or when you forgot a session weeks ago, every SSH login automatically brings you back to the tmux-ssh session you left behind.
Connect from your client:
Nothing special, just ssh user#hostname.
Don't do this on the server-side!
That is potentially dangerous because you can end up being locked-out of the remote machine. And no shell hacks / aliases / etc. are required, either.
Instead...
... make use of (your client's) ~/.ssh/config like so:
tmux 3.1 or newer¹ on the remote machine
Into your local ~/.ssh/config, put²:
Host myhost
Hostname host
User user
RequestTTY yes
RemoteCommand tmux new -A -s foobar
As pointed out by #thiagowfx, this has the side effect of making it impossible to use, e.g. ssh myhost ls /tmp and should therefore not be used with Host * ... what I like to do is to have a Host myhost section with RemoteCommand tmux ... and then in addition to that I'll have a Host MYHOST section without it.
Instead of RequestTTY yes you could call ssh with the -t switch; thank you, #kyb.
Off-topic, but if you're dealing with non-ASCII characters, I'd recommend to change that into tmux -u … for explicitly enabling Unicode support even on machines that don't have the proper environment variables set.
tmux 3.0a or older on the remote machine
Almost the same as above, but change the last line to³:
RemoteCommand tmux at -t foobar || tmux new -s foobar
¹ repology.org has a list of distros and their tmux versions
² new is short for new-session.
³ at is short for attach-session.
Only if, for some reason, you really, really can't do it client-side:
Using the remote's authorized_keys file
If you would rather not have an ~/.ssh/config file for whatever reason, or want the remote machine to force the connecting machine to connect to / open the session, add this to your remote ~/.ssh/authorized_keys:
command="tmux at -t foobar || tmux new -s foobar" pubkey user#client
This will, of course, work from all clients having the corresponding private key installed, which some might consider an upside –– but: should anything go wrong, it might not be possible to connect anymore without (semi-)physical access to the machine!
One caveat!
As #thiagowfx notes in the comments, this should not be put underneath Host * as it breaks certain things, such as git push. What I personally do is to add a second entry in all-uppercase letters for where I want to automatically be connected to tmux.
Alright, I found a mostly satisfactory solution. In my local ~/.bashrc, I wrote a function:
function ssh () {/usr/bin/ssh -t "$#" "tmux attach || tmux new";}
which basically overwrites the ssh terminal function to call the built-in ssh program with the given arguments, followed by "tmux attach || tmux new".
(The $# denotes all arguments provided on the command line, so ssh -p 123 user#hostname will be expanded to ssh -t -p 123 user#hostname "tmux attach || tmux new")
(The -t argument is equivalent to RequestTTY Force and is necessary for the tmux command.)
Connect:
ssh user#host -t "tmux new-session -s user || tmux attach-session -t user"
During session:
Use Ctrl+d to finish session (tmux window closes) or Ctrl+b d to temporary detach from session and connect to it again later.
Remember! If your server restarted session lost!
When you are inside tmux anytime you can use Ctrl+b s to see sessions list and switch current to another.
Fix your .bashrc:
I recommend you to define universal function in your .bashrc:
function tmux-connect {
TERM=xterm-256color ssh -p ${3:-22} $1#$2 -t "tmux new-session -s $1 || tmux attach-session -t $1"
}
It uses 22 port by default. Define your fast-connect aliases too:
alias office-server='tmux-connect $USER 192.168.1.123'
alias cloud-server='tmux-connect root my.remote.vps.server.com 49281'
Login without password:
And if you don't want to type password everytime than generate .ssh keys to login automatically:
ssh-keygen -t rsa
eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_rsa
Put your public key to the remote host:
ssh-copy-id -p <port> user#hostname
Additional tips:
If you want to use temporary session-id which corresponds with a local bash session use as tmux id:
SID=$USER-$BASHPID
ssh user#host -t "tmux new-session -s $SID || tmux attach-session -t $SID"
I used lines from #kingmeffisto (I'm not allowed to comment that answer) and I added an exit so terminating tmux also terminates the ssh connection. This however broke SFTP sessions so I had to check for $SSH_TTY instead of $SSH_CONNECTION.
EDIT 4/2018: Added test for interactive terminal via [[ $- =~ i ]] to allow tools like Ansible to work.
if [ -z "$TMUX" ] && [ -n "$SSH_TTY" ] && [[ $- =~ i ]]; then
tmux attach-session -t ssh || tmux new-session -s ssh
exit
fi
As described in this blog post you can ssh and then attach to an existing tmux session with a single command:
ssh hostname -t tmux attach -t 0
This is the one that actually creates a great user-experience.
It automatically starts tmux whenever you open the terminal (both physically and ssh).
You can start your work on one device, exit the terminal, and resume on the other one. If it detects someone already attached to the session it will create new session.
Put it on the server, depending on your shell ~/.zshrc or ~/.bashrc.
if [[ -z "$TMUX" ]] ;then
ID="$( tmux ls | grep -vm1 attached | cut -d: -f1 )" # get the id of a deattached session
if [[ -z "$ID" ]] ;then # if not available attach to a new one
tmux new-session
else
tmux attach-session -t "$ID" # if available attach to it
fi
fi
I have the following solution that gives you two SSH hosts to connect to: one with tmux, one without:
# Common rule that 1) copies your tmux.conf 2) runs tmux on the remote host
Host *-tmux
LocalCommand scp %d/.tmux.conf %r#%n:/home/%r/
RemoteCommand tmux new -As %r
RequestTTY yes
PermitLocalCommand yes
# Just connect.
# Notice the asterisk: makes possible to re-use connection parameters
Host example.com*
HostName example.com
User login
# Connect with tmux
Host example.com-tmux
HostKeyAlias dev.dignio.com
You might find this useful - uses ssh in a loop and reconnects to or connects to an existing tmux session so you have a nice easy reliable
way to reconnect after a network outage
#!/bin/bash
#
# reconnect to or spawn a new tmux session on the remote host via ssh.
# If the network connection is lost, ssh will reconnect after a small
# delay.
#
SSH_HOSTNAME=$1
TMUX_NAME=$2
PORT=$3
if [[ "$PORT" != "" ]]
then
PORT="-p $PORT"
fi
if [ "$TMUX_NAME" = "" ]
then
SSH_UNIQUE_ID_FILE="/tmp/.ssh-UNIQUE_ID.$LOGNAME"
if [ -f $SSH_UNIQUE_ID_FILE ]
then
TMUX_NAME=`cat $SSH_UNIQUE_ID_FILE`
TMUX_NAME=`expr $TMUX_NAME + $RANDOM % 100`
else
TMUX_NAME=`expr $RANDOM % 1024`
fi
echo $TMUX_NAME > $SSH_UNIQUE_ID_FILE
TMUX_NAME="id$TMUX_NAME"
fi
echo Connecting to tmux $TMUX_NAME on hostname $SSH_HOSTNAME
SLEEP=0
while true; do
ssh $PORT -o TCPKeepAlive=no -o ServerAliveInterval=15 -Y -X -C -t -o BatchMode=yes $SSH_HOSTNAME "tmux attach-session -t $TMUX_NAME || tmux -2 -u new-session -s $TMUX_NAME"
SLEEP=10
if [ $SLEEP -gt 0 ]
then
echo Reconnecting to session $TMUX_NAME on hostname $SSH_HOSTNAME in $SLEEP seconds
sleep $SLEEP
fi
done
byobu is a nice useful wrapper for tmux/screen. Connects to an existing session if present or creates a new one.
I use it with autossh which gracefully reconnects the ssh session. Highly recommended in case of intermittent connectivity issues.
function ssh-tmux(){
if ! command -v autossh &> /dev/null; then echo "Install autossh"; fi
autossh -M 0 $* -t 'byobu || {echo "Install byobu-tmux on server..."} && bash'
}
I know I'm reviving an old thread but I've done some work on the bashrc solution and I think it has some use:
#attach to the next available tmux session that's not currently occupied
if [[ -z "$TMUX" ]] && [ "SSH_CONNECTION" != "" ];
then
for i in `seq 0 10`; do #max of 10 sessions - don't want an infinite loop until we know this works
SESH=`tmux list-clients -t "$USER-$i-tmux" 2>/dev/null` #send errors to /dev/null - if the session doesn't exist it will throw an error, but we don't care
if [ -z "$SESH" ] #if there's no clients currently connected to this session
then
tmux attach-session -t "$USER-$i-tmux" || tmux new-session -s "$USER-$i-tmux" #attach to it
break #found one and using it, don't keep looping (this will actually run after tmux exits AFAICT)
fi #otherwise, increment session counter and keep going
done
fi
There's a cap at 10 (11) sessions for now - I didn't want to kill my server with an infinite loop in bashrc. It seems to work pretty reliably, other than the error of tmux failing on list-clients if the session doesn't exist.
Thie way allows you to reconnect to an old tmux instance if your ssh session drops. The exec saves a fork of course.
if [ -z "$TMUX" ]; then
pid=$(tmux ls | grep -vm1 "(attached)" | cut -d: -f1)
if [ -z "$pid" ]; then
tmux new -d -s $pid
fi
exec tmux attach -t $pid
fi
Append to bottom of your remote server's ~/.bashrc, (or possibly its /etc/.bashrc.shared (1)):
# ======================== PUT THIS LAST IN .BASHRC ==========================
# --- If we're run by SSH, then auto start `tmux` and possibly re-attach user.
# $- interactive only via current option flags
# -z $TMUX no tmux nesting
# $SSH_TTY SSH must be running, and in a shell
#
if [[ $- == *i* ]] && [[ -z "$TMUX" ]] && [[ -n "$SSH_TTY" ]]; then
tmux attach-session -t "$USER" || tmux new-session -s "$USER" && exit
fi
Many good tips above combined here, e.g. $- and $SSH_TTY are better I think.
And I like adding a few comments to help this old guy remember what's going on without having to look it up.
And finally, I like an exit at the end to cleanly come home when I'm done.
Thanks everyone.
Note I source a shared /etc/.bashrc.shared at the end of both user and root's .bashrc's, for common stuff used in both, like colorized ls, various aliases, functions and path extensions, i.e. I don't want redundant code in my root/.bashrc nor user/.bashrc.
This guys script works great. Just copy the bashrc-tmux file to ~/.bashrc-tmux and source it from ~/.bashrc right after the PS1 check section.

ssh client (dropbear on a router) does no output when put in background

I'm trying to automate some things on remote Linux machines with bash scripting on Linux machine and have a working command (the braces are a relict from cmd concatenations):
(ssh -i /path/to/private_key user#remoteHost 'sh -c "echo 1; echo 2; echo 3; uname -a"')
But if an ampersand is concatenated to execute it in background, it seems to execute, but no output is printed, neither on stdout, nor on stderr, and even a redirection to a file (inside the braces) does not work...:
(ssh -i /path/to/private_key user#remoteHost 'sh -c "echo 1; echo 2; echo 3; uname -a"') &
By the way, I'm running the ssh client dropbear v0.52 in BusyBox v1.17.4 on Linux 2.4.37.10 (TomatoUSB build on a WRT54G).
Is there a way to get the output either? What's the reason for this behaviour?
EDIT:
For convenience, here's the plain ssh help output (on my TomatoUSB):
Dropbear client v0.52
Usage: ssh [options] [user#]host[/port][,[user#]host/port],...] [command]
Options are:
-p <remoteport>
-l <username>
-t Allocate a pty
-T Don't allocate a pty
-N Don't run a remote command
-f Run in background after auth
-y Always accept remote host key if unknown
-s Request a subsystem (use for sftp)
-i <identityfile> (multiple allowed)
-L <listenport:remotehost:remoteport> Local port forwarding
-g Allow remote hosts to connect to forwarded ports
-R <listenport:remotehost:remoteport> Remote port forwarding
-W <receive_window_buffer> (default 12288, larger may be faster, max 1MB)
-K <keepalive> (0 is never, default 0)
-I <idle_timeout> (0 is never, default 0)
-B <endhost:endport> Netcat-alike forwarding
-J <proxy_program> Use program pipe rather than TCP connection
Amendment after 1 day:
The braces do not hurt, with and without its the same result. I wanted to put the ssh authentication to background, so the -f option is not a solution. Interesting side note: if an unexpected option is specified (like -v), the error message WARNING: Ignoring unknown argument '-v' is displayed - even when put in background, so getting output from background processes generally works in my environment.
I tried on x86 Ubuntu regular ssh client: it works. I also tried dbclient on x86 Ubuntu: works, too. So this problem seems to be specific to the TomatoUSB build - or inside the "dropbear v0.52" was an unknown fix between the build in TomatoUSB and the one Ubuntu provides (difference in help output is just the double-sized default receive window buffer on Ubuntu)... how can a process know if it was put in background? Is there a solution to the problem?
I had the similar problem on my OpenWRT router. Dropbear SSH client does not write anything to output if there is no stdin, e.g. when run by cron. I presume that & has the same effect on process stdin (no input).
I found some workaround on author's bugtracker. Try to redirect input from /dev/zero.
Like:
ssh -i yourkey user#remotehost "echo 123" </dev/zero &
It worked for me as I tried to describe at my blog page.

set environment variable SSH_ASKPASS or askpass in sudoers, resp

I'm trying to login to a ssh server and to execute something like:
ssh user#domain.com 'sudo echo "foobar"'
Unfortunately I'm getting an error:
sudo: no tty present and no askpass program specified
Google told me to either set the environment variable SSH_ASKPASS or to set askpass in the sudoers file. My remote machine is running on Debian 6 and I've installed the packages ssh-askpass and ssh-askpass-gnome and my sudoers file looks like this:
Defaults env_reset
Defaults askpass=/usr/bin/ssh-askpass
# User privilege specification
root ALL=(ALL) ALL
user ALL=(ALL) ALL
Can someone tell what I'm doing wrong and how to do it better.
There are two ways to get rid of this error message. The easy way is to provide a pseudo terminal for the remote sudo process. You can do this with the option -t:
ssh -t user#domain.com 'sudo echo "foobar"'
Rather than allocating a TTY, or setting a password that can be seen in the command line, do something like this.
Create a shell file that echo's out your password like:
#!/bin/bash
echo "mypassword"
then copy that to the node you want using scp like this:
scp SudoPass.sh somesystem:~/bin
Then when you ssh do the following:
ssh somesystem "export SUDO_ASKPASS=~/bin/SudoPass.sh;sudo -A command -parameter"
Another way is to run sudo -S in order to "Write the prompt to the standard error and read the password from the standard input instead of using the terminal device" (according to man) together with cat:
cat | ssh user#domain.com 'sudo -S echo "foobar"'
Just input the password when being prompted to.
One advantage is that you can redirect the output of the remote command to a file without "[sudo] password for …" in it:
cat | ssh user#domain.com 'sudo -S tar c --one-file-system /' > backup.tar
Defaults askpass=/usr/bin/ssh-askpass
ssh-askpass requires X server, so instead of providing a terminal (via -t, as suggested by nosid), you may forward X connection via -X:
ssh -X user#domain.com 'sudo echo "foobar"'
However, according to current documentation, askpass is set in sudo.conf as Path, not in sudoers.
How about adding this in the sudoers file:
user ALL=(ALL) NOPASSWD: ALL

Shell script to append new lines to etc/hosts and Apache httpd-vhosts.conf in Mac OSX 10.6

I am using Mac OSX 10.6 and doing web development on it. I know a small amount about writing shell scripts, but I am not really versed in them as of yet.
What I would like to do is to write a shell script that will simply ask for a local site alias and the document directory and it will then append the new alias onto hosts with something like "127.0.0.1 mysite.local" on a new line at the bottom of etc/hosts.
Then the script would append Apache's httpd-vhosts.conf file with something like this:
<VirtualHost *:80>
DocumentRoot "/Repositories/myproject/mysite.com/trunk/htdocs"
ServerName mysite.local
ServerAlias mysite.localhost
</VirtualHost>
Then it would finally run the command to restart my Apache server. Now I know the terminal command to restart Apache, that is simple enough. I also know how to read in the site name and path from the user running the script. Such as below:
#!/bin/bash
read -p "New local site name: " site
read -p "Site path (ex:/Repositories/myproject/mysite.com/trunk/htdocs): " sitepath
What I don't know how to do is to append text to a file from terminal.
Any thoughts or helpful ideas?
Thanks,
Patrick
Untested, but it should work:
#!/bin/bash
read -p "New local site name: " SITE
read -p "Site path (ex:/Repositories/myproject/mysite.com/trunk/htdocs): " SITEPATH
#/etc/hosts
cp /etc/hosts /etc/hosts.original
echo -e "127.0.0.1\t${SITE}.local" >> /etc/hosts
#httpd-vhosts.conf
VHOSTSFILE="/etc/apache2/httpd-vhosts.conf"
cp $VHOSTSFILE ${VHOSTSFILE}.original
echo "<VirtualHost *:80>" >> $VHOSTSFILE
echo -e "\tDocumentRoot \"${SITEPATH}\"" >> $VHOSTSFILE
echo -e "\tServerName ${SITE}.local" >> $VHOSTSFILE
echo -e "\tServerAlias ${SITE}.localhost" >> $VHOSTSFILE
echo '</VirtualHost>' >> $VHOSTSFILE
#restart apache
>> redirects the output to the given file, appending the contents to the file. I’m also using -e to allow \t to be expanded to a tab character.
Note that you need to run this script with sudo. I've also included commands to backup the original files before modifying them, just in case.
I made some tweaks and did some extra stuff in the above answer, because this didn't work for me but it helped me to come up with another solution. This answer is only for Mac users.
First go in your /etc/apache2/httpd.conf and uncomment virtual host reference, which is this line Include /private/etc/apache2/extra/httpd-vhosts.conf
Now create a bash file I did that in my user’s home named as imran, you need to replace it with your username.
I placed it inside /Users/imran named as create_new_site.sh. I gave it executeable permissions, so it can be easily executed using chmod +x create_new_site.sh
Code for the script is as below:
#!/bin/bash
read -p "New local site name (prefix to .local): " SITE
SITEPATH=$SITE
sudo chmod -R a+w /Users/imran/Sites/web
SITEPATH="/Users/imran/Sites/web/${SITEPATH}"
mkdir -p $SITEPATH
#/etc/hosts
cp /etc/hosts /etc/hosts.original
echo -e "127.0.0.1\t${SITE}.local" >> /etc/hosts
#httpd-vhosts.conf
VHOSTSFILE="/etc/apache2/extra/httpd-vhosts.conf"
cp $VHOSTSFILE ${VHOSTSFILE}.original
echo "<VirtualHost *:80>" >> $VHOSTSFILE
echo -e "\tDocumentRoot \"${SITEPATH}\"" >> $VHOSTSFILE
echo -e "\tServerName ${SITE}.local" >> $VHOSTSFILE
echo '</VirtualHost>' >> $VHOSTSFILE
echo '<?php phpinfo();' > "${SITEPATH}/phpinfo.php"
sudo chmod -R a+w $SITEPATH
#restart apache
sudo apachectl restart
echo "All done! visit, let's visit http://${SITE}.local/phpinfo.php"
Once that is done you can start creating new sites using sudo ./create_new_site.sh. Remember that you need to be in your home directory, which you can go via cd ~ command. Now let's suppose you created a site with name test. You should be able to visit http://test.local/phpinfo.php to see your vhost working.