syntax error near unexpected token `&' (using "|&") - bash

I have syntax error near unexpected token & in next :
in bash scripts its'go like this :
#!/bin/bash
var1=`(/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null)|& grep real|awk '{print $2}'`
when i issue this command on cli i get good output, problem is when invoke this in script i can get any output from var1
./check_cdifonline.sh: command substitution: line 2: syntax error near unexpected token `&'
./check_cdifonline.sh: command substitution: line 2: `(/usr/bin/time cdifonline -CD 186821 -ALL >/dev/null) | & grep real | awk '{print $2}''

You can use the sequence |& to pipe both stdout and stderr from one process to another.
You cannot have a space between the | and the &. (csh and tcsh allow a space; bash does not.) I suspect you happen to be typing it without the space when you run the command interactively; the syntax is the same either way.
This:
foo |& bar
is shorthand for this:
foo 2>&1 | bar
UPDATE :
With bash 3.2.25, the |& token is not recognized; was added as a new feature in bash 4.1. Running your script with the older bash, I get the same error message you do.
To make your script compatible with older versions of bash, just do the equivalent redirection without using the |& operator:
#!/bin/bash
var1=`(/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | grep real | awk '{print $2}'`
Further refinements: Use $(...) rather than `...`:
#!/bin/bash
var1=$((/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | grep real | awk '{print $2}')
You can also incorporate the grep search into the awk command:
#!/bin/bash
var1=$((/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | awk '/real/ {print $2}')
Warning: I have not thoroughly tested these beyond verifying that they run without syntax errors.
I still see no difference between |& and | &. Is it possible that /bin/bash is a different version than what you're running interactively? Try /bin/bash --version and echo $BASH_VERSION.

Try change to:
var1=$(/usr/bin/time cdifonline -CD 186821 -ALL >/dev/null | awk '/real/ {print $2}')

Thanks Keith I have no problems anymore you saved my day :) so the bash version was the problem and with avoiding of & I have no errors, thanks also for fine tuning :)
so this works with my bash version
#!/bin/bash
var1=`(/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | grep real | awk '{print $2}'`

Related

Execute command via ssh [duplicate]

This question already has an answer here:
Bash command substitution on remote host [duplicate]
(1 answer)
Closed 3 years ago.
I want to kill process. Without kill cmd it works fine. But with kill cmd i get:
grep: invalid option -- 'S'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
awk: cmd. line:1: {print
awk: cmd. line:1: ^ unexpected newline or end of string
kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
Doesn't work:
ssh someUser#someHost kill $(ps -aux | grep 'screen -S cats' | awk '{print $2}')
Works fine:
ssh someUser#someHost ps -aux | grep 'screen -S cats' | awk '{print $2}'
The command substitution runs ps locally, to produce the argument for the remote kill command.
To make the command substitution run remotely, quote the entire string (which is a good idea; you generally don't want ssh having to figure out how to join its arguments into a single command).
# Using $'...', which may contain escaped single quotes
ssh someUser#someHost $'kill $(ps -aux | awk \'/screen -S cats/ {print $2}\''
or
# Using standard double quotes, but making the user responsible
# for escaping any dollar signs that need to be passed literally.
ssh someUser#someHost "kill \$(ps -aux | awk '/screen -S cats/ {print \$2}'"

Bash- Running a command on each grep correspondence without stopping tail -n0 -f

I'm currently monitoring a log file and my ultimate goal is to write a script that uses tail -n0 -f and execute a certain command once grep finds a correspondence. My current code:
tail -n 0 -f $logfile | grep -q $pattern && echo $warning > $anotherlogfile
This works but only once, since grep -q stops when it finds a match. The script must keep searching and running the command, so I can update a status log and run another script to automatically fix the problem. Can you give me a hint?
Thanks
use a while loop
tail -n 0 -f "$logfile" | while read LINE; do
echo "$LINE" | grep -q "$pattern" && echo "$warning" > "$anotherlogfile"
done
awk will let us continue to process lines and take actions when a pattern is found. Something like:
tail -n0 -f "$logfile" | awk -v pattern="$pattern" '$0 ~ pattern {print "WARN" >> "anotherLogFile"}'
If you need to pass in the warning message and path to anotherLogFile you can use more -v flags to awk. Also, you could have awk take the action you want instead. It can run commands via the system() function where you pass the shell command to run

commands not found when running script

I have a very basic script that keeps spitting back that the commands are not found. Ive looked all over this site and can not find an answer that works for me. The path to bash is correct. Ive checked the script with od. Ive run dos2unix. None of this helps me.
SCRIPT:
#!/bin/bash
HYBRISPROC=`ps -eo pid,command | grep [h]ybris | grep -v grep | awk '{print $1}'`
echo "Looking for Hybris..."
echo $HYBRISPROC
RESULTS:
./HybrisStopStart.sh: line 5: ps: command not found
./HybrisStopStart.sh: line 5: grep: command not found
./HybrisStopStart.sh: line 5: awk: command not found
./HybrisStopStart.sh: line 5: grep: command not found
Looking for Hybris...
Any ideas? If I run the command just on its own it works fine. Ive tried it as sudo as well and et the same results.
TIA
How about it?
#!/bin/bash
HYBRISPROC=`ps -eo pid,command | grep [h]ybris | grep -v grep | awk '{print $1}'`
echo "Looking for Hybris..."
echo "$HYBRISPROC"
(OR)
#!/bin/bash
HYBRISPROC="ps -eo pid,command | grep [h]ybris | grep -v grep | awk '{print $1}'"
echo "Looking for Hybris..."
bash -c "$HYBRISPROC"
(OR)
#!/bin/bash
HYBRISPROC="ps -eo pid,command | grep [h]ybris | grep -v grep | awk '{print $1}'"
echo "Looking for Hybris..."
eval "$HYBRISPROC"
TOTALY:
you can see the difference:
#!/bin/bash
LS=`ls -l`
echo $LS #nasty way
echo
echo "$LS" #good way
Try to add
PATH="$PATH:/usr/bin:/bin"
before code. Looks like bin directory is not on your path. So the commands are not found.

Grep output of command and use it in "if" statement, bash

Okay so here's another one about the StarMade server.
Previously I had this script for detecting a crash, it would simply search through the logs:
#!/bin/bash
cd "$(dirname "$0")"
if ( grep "[SERVER] SERVER SHUTDOWN" log.txt.0); then
sleep 7; kill -9 $(ps -aef | grep -v grep | grep 'StarMade.jar' | awk '{print $2}')
fi
It would find "[SERVER] SERVER SHUTDOWN" and kill the process after that, however this is not a waterproof method, because with different errors it could be possible that the message doesn't appear, rendering this script useless.
So I have this tool that can send commands to the server, but returns an EOF exception when the server is in a crashed state. I basically want to grab the output of this command, and use it in the if-statement above, instead of the current grep command, in such a way that it would execute the commands below when the grep finds "java.io.EOFException".
I could make it write the output to a file and then grep it from there, but I wonder, isn't there a better/more efficient method to do this?
EDIT: okay, so after a bit of searching I put together the following:
if ( java -jar /home/starmade/StarMade/StarNet.jar xxxxx xxxxx /chat) 2>&1 > /dev/null |grep java.io.EOFException);
Would this be a valid if-statement? I need it to match "java.io.EOFException" in the output of the first command, and if it matches, to execute something with "then" (got that part working).
Not sure to solve your problem, but this line:
ps -aef | grep -v grep | grep 'StarMade.jar' | awk '{print $2}'
could be change to
ps -aef | awk '/[S]tarMade.jar/ {print $2}'
The [S] prevents awk from finding itself.
Or just like this to get the pid
pidof StarMade.jar

Bash script doesn't work as cronjob

Hi i wrote the following bash script:
cat /home/xyz/wlandiscovery.sh
#!/bin/bash
DATE=`date +%d-%m-%Y__%H:%M:%S`
#Get the current standard interface e.g. eth0
INTERFACE=`route | grep '*' | awk '{print $8}'`
#Check if mac is available
if /usr/bin/arp-scan --interface $INTERFACE -l -r 5 | grep "xx:xx:xx:xx:xx:xx"
then
echo -e "$DATE AVAILABLE!" >> /home/xyz/wlandiscovery.log
else
echo -e "$DATE NOT AVAILABLE" >> /home/xyz/wlandiscovery.log
fi
exit 0
If i run this and the mac is available i get "AVAILABLE", if i disconnect the device it give "NOT AVAILABLE"...so run as expected.
But if i run it as Cronjob every 5 Minutes I get always "NOT AVAILABLE": (on a Debian system)
crontab -e
#......
*/5 * * * * /bin/bash /home/xyz/wlandiscovery.sh
Whats the problem here?
INTERFACE=`route | grep '*' | awk '{print $8}'`
On my system, route is /usr/sbin/route. /usr/sbin is most likely not in cron's PATH. Specify the full path:
INTERFACE=`/usr/sbin/route | awk '$2 == "*" {print $8}'`
Compare the command line output of the following on your Mac and Debian boxes:
INTERFACE=route | grep '*' | awk '{print $8}'
Is it the same? It should be in order to work.
Then, compare the command line output of:
/usr/bin/arp-scan --interface $INTERFACE -l -r 5 | grep "xx:xx:xx:xx:xx:xx"
Alright, now its working. seems that $PATH with crontab is not equal to $PATH in my Terminal prompt... if i do /sbin/route and /usr/bin/awk and /bin/grep it works.

Resources