Here is the chunk of code for reference:-
Output:
I have checked the variable values using echo and those looks fine.
But what I want do achieve is searching logs on remote hosts using grep which does not give any output.
for dir in ${log_path}
do
for host in ${Host}
do
if [[ "${userinputserverhost}" == "${host}" ]]
then
ssh -q -T username#userinputserverhost "bash -s" <<-'EOF' 2>&1 | tee -a ${LogFile}
echo -e "Fetching details: \n"
`\$(grep -A 5 -s "\${ID}" "\${dir}"/archive/*.log)`
EOF
fi
break
done
done
First, remove all the crap around the grep.
Second, you're overquoting your vars.
Third, skip the "bash -s" if you can.
ssh -q -T username#userinputserverhost <<-'EOF' 2>&1 | tee -a ${LogFile}
echo -e "Fetching details: \n"
grep -A 5 -s "${ID}" "${dir}"/archive/*.log
EOF
Fourth, I don't see where $ID is set...so if that's being loaded on the remote system by the login or something, then that one would need the dollar sign backslashed.
Finally, be aware that here-docs are great, but sometimes here-strings are simpler if you can spare the quotes.
$: ssh 2>&1 dudeling#sandbox-server '
> date
> whoami
> ' | tee -a foo.txt
Fri Apr 30 09:23:09 EDT 2021
dudeling
$: cat foo.txt
Fri Apr 30 09:23:09 EDT 2021
dudeling
That one is more a matter of taste. Even better, if you can, write your remote-script to a local file & use that. And of course, you can always add set -vx into the script to see what gets remotely executed.
cat >tmpScript <<-'EOF'
echo -e "Fetching details: \n"
set -vx
grep -A 5 -s "${ID}" "${dir}"/archive/*.log
EOF
ssh <tmpScript 2>&1 -q -T username#userinputserverhost | tee -a ${LogFile}
Now you have an exact copy of what was issued for debugging.
Thanks Paul for spending time and coming up with suggestions/solutions.
I have managed to get it working couple of days back. Would have felt happy to say that your solution worked 100% but even satisfied that I got it sorted on my own as it helped me learn some new stuff.
FYI - grep -A 5 -s "${ID}" "${dir}"/archive/*.log - this will work but only by using shell built-in 'declare -p' to declare the variables within EOF. Also, I read somewhere and it is recommended to use EOF unqouted as it caters variable expansion to remote hosts without any trouble.
Below piece of code is working for me in bash:
ssh -q -T username#userinputserverhost <<-EOF 2>&1 | tee -a ${LogFile}
echo -e "Fetching details: \n"
$(declare -p ID)
$(declare -p dir)
grep -A 5 -s "${ID}" "${dir}"/archive/*.log
EOF
I have this that is working pretty good in openwrt:
#!/bin/sh
#set -x #debug
while true; do
wget -O /tmp/extip 'http://ifconfig.me/ip' 2>/dev/null
EXT_IP=$(cat /tmp/extip)
INT_IP="$(ip addr show dev wwan0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)"
ROOTER=/usr/lib/rooter
[ -z $EXT_IP ] && continue
if [ $(echo "$INT_IP" | grep "$EXT_IP" -q; echo $?) -eq 1 ]; then
/sbin/ifup wan1
$ROOTER/pwrtoggle.sh 1
echo "NAT-DETECT: External ($EXT_IP) does not match Internal ($INT_IP); Reconnecting WAN1..." > /dev/kmsg
/etc/init.d/firewall restart
/etc/init.d/miniupnpd restart
fi
sleep 30
done
#set +x #debug
How do I make this script run in the boot (or after sometime) and let it running in background forever checking current IP status and doing its job? Also it looks like it's not good to have a init script with "sleep", because it's considered bad form. What would be an optimized form of this script to match my purpose?
Thanks in advance!
I installed GNU screen on my OpenWRT and in /etc/rc.local I have something like this:
# start screen in detached mode
screen -dm -S boot -c /dev/null bash /root/bin/monitor.sh
It will run in background. You can also attach to it with screen -r boot after login.
You can try if it works for you.
I need to know an another process pid which is executed as a command in the bash script like a nmap scan etc as an when the process is created I can display a bar or a spinner
#!/bin/sh
G='\033[0;32m'
B='\033[0m'
${G}Enter IP TAIL LIKE 0.1 OR 1.1${B}"
read v
${G}ENTER Device NAME ${B}"
read k
nmap -A -Pn -sV 192.168.$v -oN /tmp/op
//here i want a while loop for displaying a spinner
edit code is updated Thts the code in case tht was not visible properly ^^
As the pid dies when its completed I can use it as a count or a flag or something similar to end the spinner.
I'm working on Kali nethunter.
P.S This is my first time on stack overflow pls forgive me if its too stupid or tell me if I missed something.
A starting point:
#!/bin/bash
echo "Enter IP:"
read -r ip
# `&` runs in parallel
# always quote variables
nmap "$ip" &
# `$!` get's the background process PID
pid=$!
...
# you can see if a pid is running by checking exit status of `kill -0`
while kill -0 "$pid" 2>&1 >/dev/null; do
printf ...
...
done
nmap -A -Pn -sV 192.168.0.1 -p -oN /tmp/op >/dev/null & pid=$!
i=1
sp="/-\|"
echo -n ' '
while kill -0 "$pid" 2>&1 >/dev/null;
do
printf "\b${sp:i++%${#sp}:1}"
done
*Problem solved thanks to * kamil cuk
This question already has answers here:
Execute a command on remote hosts via ssh from inside a bash script
(4 answers)
Closed 7 years ago.
I need a help with a bash script that connect to server as root, execute some commands and then exit from the server.
I tried this script but when login login to server performed the command not running !
#!/bin/bash
sudo ssh -o ConnectTimeout=10 $1 'exit'
if [ $? != 0 ]; then
echo "Could not connect to $1 , script stopped"
exit
fi
sudo ssh $1
echo "SRV=`cat /etc/puppet/puppet.conf | grep -i srv_domain | awk '{print $3}'`"
echo $SRV
echo "puppetMaster=`host -t srv _x-puppet._tcp.$SRV | head -1 | awk '{print $8}' | cut -f1 -d"."`"
echo $puppetMaster
'exit'
I'm surprised nobody has suggested a heredoc yet.
sudo ssh "$1" <<'EOF'
SRV=`cat /etc/puppet/puppet.conf | grep -i srv_domain | awk '{print $3}'`
echo $SRV
echo "puppetMaster=`host -t srv _x-puppet._tcp.$SRV | head -1 | awk '{print $8}' | cut -f1 -d"."`"
echo $puppetMaster
EOF
This feeds everything from the <<'EOF' until the line starting with EOF into the stdin of ssh, to be received and run by the remote shell.
The commands following ssh machine in a script are not run on the machine. They will be run on the local machine once the ssh exits.
Either specify the commands to run as an argument of ssh, or alternatively, run ssh and make it read the commands from standard input, and send the commands to it.
ssh machine ls
# or
echo ls | ssh machine
You seem to be a little confused as to what runs where.
ssh -o ConnectTimeout=10 $1 'exit'
will connect to $1, run exit, and disconnect.
ssh -o ConnectTimeout=10 $1 'echo hello world'
will print hello world on
the server and then disconnect.
ssh $1
will open up a shell on the remote. After the shell has ended, the following commands will run locally.
echo "SRV=`cat /etc/puppet/puppet.conf | grep -i srv_domain | awk '{print $3}'`"
echo $SRV
echo "puppetMaster=`host -t srv _x-puppet._tcp.$SRV | head -1 | awk '{print $8}' | cut -f1 -d"."`"
echo $puppetMaster
'exit'
What you probably want is start bash on the remote and forward to it the commands you want to give it via stdin.
echo "my commands" | ssh $1 bash
Technically, you don't need that bash -- ssh will start bash even without it (but with different rc files).
How do you check if a process on Mac OS X is running using the process's name in a Bash script?
I am trying to write a Bash script that will restart a process if it has stopped but do nothing if it is still running.
Parsing this:
ps aux | grep -v grep | grep -c [-i] $ProcessName
...is probably your best bet.
ps aux lists all the currently running processes including the Bash script itself which is parsed out by grep -v grep with advice from Jacob (in comments) and grep -c [-i] $ProcessName returns the optionally case-insensitive integer number of processes with integer return suggested by Sebastian.
Here's a short script that does what you're after:
#!/bin/bash
PROCESS=myapp
number=$(ps aux | grep -v grep | grep -ci $PROCESS)
if [ $number -gt 0 ]
then
echo Running;
fi
EDIT: I initially included a -i flag to grep to make it case insensitive; I did this because the example program I tried was python, which on Mac OS X runs as Python -- if you know your application's case exactly, the -i is not necessary.
The advantage of this approach is that it scales with you -- in the future, if you need to make sure, say, five instances of your application are running, you're already counting. The only caveat is if another application has your program's name in its command line, it might come up -- regular expressions to grep will resolve that issue, if you're crafty (and run into this).
Research the Darwin man pages for ps, grep, and wc.
A shorter solution:
if pgrep $PROCESS_NAME; then
echo 'Running';
fi
Explanation:
pgrep exits with 0 if there is a process matching $PROCESS_NAME running, otherwise it exist with 1.
if checks the exit code of pgrep, and, as far as exit codes go, 0 is success.
Another way is to use (abuse?) the -d option of the killall command. The -d options won't actually kill the process, but instead print what will be done. It will also exit with status 0 if it finds a matching process, or 1 if it does not. Putting this together:
#!/bin/bash
`/usr/bin/killall -d "$1" &> /dev/null`
let "RUNNING = ! $?" # this simply does a boolean 'not' on the return code
echo $RUNNING
To give credit where its due, I originally pulled this technique from a script in the iTunes installer.
This simple command will do the trick. The brackets around the process name prevent the grep command from showing in the process list. Note there is no space after the comma. There may be some portability issues as ps on some unix systems may require a dash before the options:
ps axo pid,command | grep "[S]kype"
The advantage is that you can use the results in an if statement like this:'
if [[ ! $(ps axo pid,command | grep "[i]Tunes.app") ]]; then
open -a iTunes
fi
Or if you prefer this style:
[[ ! $(ps axo pid,command | grep "[S]kype") ]] && open -a Skype || echo "Skype is up"
Another advantage is that you can get the pid by adding a pipe to awk '{print $1}'.
echo "iTunes pid: $(ps axo pid,command | grep "[i]Tunes.app" | awk '{print $1}')"
You can use either killall or kill, depending on if you are trying to find the task by PID or by name.
By Name:
if ! killall -s -0 $PROCESS_NAME >/dev/null 2>&1; then
# Restart failed app, or do whatever you need to prepare for starting the app.
else
at -f $0 +30seconds # If you don't have this on cron, you can use /usr/bin/at
fi
By PID:
if ! kill -0 $PID 2>/dev/null; then
# Restart app, do the needful.
else
at -f $0 +30seconds
fi
If you look at the OSX Manual you will see a different set of process management commands; since it's not the linux kernel, it makes sense that they would manage processes differently.
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/killall.1.html
A sample output from my terminal (striking out the user and hostname, of course):
user#localhost:~$ kill -0 782 # This was my old, stale SSH Agent.
bash: kill: (782) - No such process
user#localhost:~$ echo $?
1
user#localhost:~$ kill -0 813 # This is my new SSH agent, I only just created.
user#localhost:~$ echo $?
0
The return code from a kill -0 will always result in a safe way to check if the process is running, because -0 sends no signal that will ever be handled by an application. It won't kill the application, and "kill" is only called "kill" because it's usually used to stop an application.
When you look at the interfaces it uses in the source, you'll see that it's actually interacting with the process table directly (and not grepping a potentially loaded output from ps), and just sending a signal to an application. Some signals indicate the application should shutdown or stop, while other signals tell it to restart services, or re-read configuration, or re-open file descriptors to log files that have been recently rotated. There are a plethora of things that "kill" and "killall" can do that doesn't terminate the application, and it's used regularly to simply send a signal to the application.
I lack the reputation to comment on the killall answer above, but there's killall -s for doing it without sending any signals:
killall -s "$PROCESSNAME" &> /dev/null
if [ $? -eq 0 ]; then
echo "$PROCESSNAME is running"
# if you also need the PID:
PID=`killall -s "$PROCESSNAME" | awk '{print $3}'`
echo "it's PID is $PID"
fi
It has for sure!
pgrep, pkill and pfind for OpenBSD and Darwin (Mac OS X)
http://proctools.sourceforge.net
(also available via MacPorts: port info proctools )
pidof by nightproductions.net
I've extended a pidof script found on the net to use regular expressions (usually substrings) and be case insensitive
#!/bin/sh
ps axc |awk "BEGIN{ n=tolower(\"$1\")}\
tolower(\$5) ~n {print \$1}";
just create a script named "pidof" with this content, and put it in you path, i.e. in one of the dirs in
echo $PATH
and make it executable (maybe using sudo)
chmod 755 /usr/local/bin/pidof
and use it like this, of course
kill -9 `pidof pyth`
does Mac have pidof? ...
if pidof $processname >/dev/null ; then echo $processname is running ; fi
Perhaps too late for the OP but this may help others who find this thread.
The following modification of the amrox theme above works well for restarting applications on my OS X:
killall -d TextEdit &> /dev/null && killall TextEdit &> /dev/null; open -a TextEdit
I use the following AppleScript to update and restart daemons:
tell application "System Events" to set pwd to POSIX path of container of (path to me)
do shell script "launchctl unload -w /Library/LaunchDaemons/time-test.plist; cp -f " & quoted form of pwd & "/time-test.plist /Library/LaunchDaemons; launchctl load -w /Library/LaunchDaemons/time-test.plist" with administrator privileges
It assumes the original or updated plist file is in the same directory as the AppleScript.