Why does awk fail when part of ssh command? [duplicate] - bash

This question already has answers here:
How to use bash $(awk) in single ssh-command?
(6 answers)
awk remote ssh command
(1 answer)
Run a remote awk command using ssh
(1 answer)
Closed 4 years ago.
When I ssh into a server and run the command, it works:
$ssh -q postgres#XXXXX
Last login: Mon Mar 12 12:30:16 2018 from 10.101.XXX.X
[postgres#pgsdba203 ~]$ df -hP | grep pgsql | awk '{ if ($5 >= 70) print $0 }'
/dev/mapper/pgvg-pg_log 9.9G 7.2G 2.2G 77% /var/lib/pgsql/data/pg_log
But not when it's part of an ssh command parameter:
$ ssh -q postgres#XXXXX "df -hP | grep pgsql | awk '{ if ($5 >= 70) print $0 }'"
awk: { if ( >= 70) print -bash }
awk: ^ syntax error
Since the awk command is in single quotes, I'd have expected the $5 to be preserved and passed directly to server XXXXX.
EDIT: the end goal is to make the server name into a variable and call ssh from within a bash for loop.

What I would do :
ssh -q postgres#XXXXX <<'EOF'
df -hP | awk '/pgsql/ && $5 >= 70'
EOF
or in a for loop
for server in foo bar base; do
ssh -q postgres#$server <<'EOF'
df -hP | awk '/pgsql/ && $5 >= 70'
EOF
done

As an easy-to-define pattern, which works even when you need to pipe stdin into your remote code: Define a shell function, and tell the shell itself to emit that function's literal text substituted into the remote command:
myfunc() { df -hP | grep pgsql | awk '{ if ($5 >= 70) print $0 }'; }
ssh -q postgres#XXXX "$(declare -f myfunc); myfunc"

Related

How to use awk {print} inside an inline ssh command

I am trying to run an inline ssh command which looks like this:
ssh user#127.0.0.1 "df / -h | awk 'FNR == 2 {print $3}'"
I would expect the output to be 3.8G (as this is the second line, third column) but instead, I am getting /dev/sda1 6.9G 3.8G 2.8G 58% /(the entire second line).
This means that the FNR == 2 is working but the {print $3} is not.
If I run that command directly on the machine that I am ssh'ing into then I get the expected result, just not when calling it through an inline ssh command as above.
This code will eventually ran within a bash script. Is it not possible to use print in this way? If not, is there another method that you can suggest? I am relatively new to terminal life so please bear with me.
The problem resides in the way you pass you ssh arguments.
By calling:
ssh user#127.0.0.1 "df / -h | awk 'FNR == 2 {print $3}'"
You are passing two arguments:
user#127.0.0.1
"df / -h | awk 'FNR == 2 {print $3}'"
Since your second argument is given inside double quotes, the $3 variable will be expanded. You can prevent this variable expansion by escaping the dollar sign:
ssh user#127.0.0.1 "df / -h | awk 'FNR == 2 {print \$3}'"
The joys of shell quoting. The line:
ssh user#127.0.0.1 "df / -h | awk 'FNR == 2 {print $3}'"
Is parsed by the shell, which invokes ssh with two arguments:
user#127.0.01 and df / -h | awk 'FNR == 2 {print }' The $3 was interpolated, and (I'm assuming) was empty. To prevent that, you have many options. One of which is:
ssh user#127.0.0.1 << \EOF
df / -h | awk 'FNR == 2 {print $3}'
EOF
another is:
ssh user#127.0.0.1 sh -c '"df / -h | awk '"'"'FNR == 2 {print $3}'"'"'"'

shell script not running but command line running [duplicate]

This question already has answers here:
How do I use shell variables in an awk script?
(7 answers)
Closed 5 years ago.
I have a Error Log file with contents as -
2017/11/06 13:17:05 [notice] 18164#18164: signal process started
.
.
.
I have command that will extract the date and notice,warn message
cat whole_error.log | cut -d" " -f1,3,5-20 | sort -nr | grep "warn\|notice" | awk '$1 >= 2017/09/02 && $1 <= 2017/11/06' | awk '{print $1 " " $2" " $3}'
Its working fine entirely, i am getting the expected output
But, i want to take the start date and end date as command line argument input
and for that, i wrote the script as -
#!/bin/bash
file_name=$1
start_date=$2
end_date=$3
cat $file_name | cut -d" " -f1,3,5-20 | sort -nr | grep "warn\|notice" | awk '$1 >= $start_date && $1 <= $end_date' | awk '{print $1 " " $2" " $3}'
But its not returning anything. No error message nothing..Just the prompt arrives again.
How to fix this..
Use -v to pass shell variables into awk:
#!/bin/bash
file_name=$1
start_date=$2
end_date=$3
<"$file_name" cut -d" " -f1,3,5-20 \
| sort -nr \
| awk -v start_date="$start_date" -v end_date="$end_date" \
'/warn|notice/ && $1 >= start_date && $1 <= end_date {print $1 " " $2" " $3}'

ansible shell escape single and double quotes

I'm trying to execute this command:
ps -eo pid,args --cols=10000 | awk '/\/opt\/logstash\/logstash-1.5.3\// && $1 != PROCINFO["pid"] { print $1 }'
whith ansible -m shell module (not working example):
ansible -m shell -a '"'ps -eo pid,args --cols=10000 | awk '/\/opt\/logstash\/logstash-1.5.3\// && $1 != PROCINFO[\'pid\'] { print $1 }' '"' all
One of the ways would be to put that into a file, but still it would be nice to run as a command - any ideas?
Bash escaping rules will do:
ansible localhost -m shell -a "ps -eo pid,args --cols=10000 | awk '/\\/opt\\/logstash\\/logstash-1.5.3\\// && \$1 != PROCINFO[\"pid\"] { print \$1 }'"
Mine alternative version that worked:
ansible -m command -a "ps a |grep -E '/opt/logstash/logstash-1.5.3/vendor/jruby' " all --sudo
Check if the process are running:
ansible -m shell -a "ps aux |grep -E '/opt/logstash/logstash-1.5.3/vendor/jruby'|grep -v -e grep |wc" all
A simple way (i.e. without having to rewrite the command much or introduce a bunch of escapes) is to use a temporary variable.
Your original command:
ps -eo pid,args --cols=10000 \
| awk '/\/opt\/logstash\/logstash-1.5.3\// && $1 != PROCINFO["pid"] { print $1 }'
Corresponding ansible call:
x='/\/opt\/logstash\/logstash-1.5.3\// && $1 != PROCINFO["pid"] { print $1 }'; \
ansible all -m shell -a "ps -eo pid,args --cols=10000 | awk '$x'"

Variable value not set in ssh -X [duplicate]

This question already has an answer here:
Executing ssh command in a bash shell script within a loop [duplicate]
(1 answer)
Closed 9 years ago.
I am Oracle DBA and i am doing some scripting to check if database is live or not on our large number of servers.
I am trying to set value to variable in ssh -X e.g
[oracle#proddb02]$ DB_STAT=`ssh -X proaddb01 'ps -ef | grep pmon | grep -v grep' | awk '{ print $8 }'`
[oracle#proddb02]$ echo $DB_STAT
ora_pmon_pconn01
Above example works perfectly but as i am using ssh command i cannot loop using while as it exit at the first line file which include list of the servers.
so i have to add /dev/null to the command so that it should not exit the loop. but this does not set the variable value.
When i echo the variable it gives nothing.
[oracle#proddb02]$ DB_STAT=`ssh -X proddb01 'ps -ef | grep pmon | grep -v grep' | awk '{ print $8 }'</dev/null`
[oracle#proddb02]$ echo $DB_STAT
[oracle#proddb02]$ echo $DB_STAT
The loop code is
[oracle#proddb02]$cat test.sh
while read line
do
INST_VAR=`echo $line | awk '{ print $1 }'`
HOST_VAR=`echo $line | awk '{ print $2 }'`
SERVER_NAME=$HOST_VAR
INSTANCE_NAME=$INST_VAR
DB_STAT=`ssh -X proaddb01 'ps -ef | grep pmon | grep -v grep' | awk '{ print $8 }'`
echo $DB_STAT
done < host_list.lst
Any help would be much appreciated.
Just do:
DB_STAT=`ssh -X proaddb01 "ps -ef | awk '/[p]mon/'{ print $8 }"`
Here you use:
// to filter the input stream (like grep but witj awk);
the trick with [p]grep to exclude the same line from ps (because [p]grep string will not be found with [p]grep template).

shell commands won't run in bash script

I'm trying to pass a parameter to a bash script:
"words.sh surf"
#!/bin/bash
#words.sh
#purpose:
#
# to return a list of words
# sorted by the length of each word
#
i=$1
cat ~/wordlist | grep $i | awk '{ print length(),$0 | "sort -n" }'
and I'm getting this message:
usage: grep [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZ] [-A num] [-B num] [-C[num]].
awk: syntax error at source line 1
context is.
{ print length(), >>> -/bin/bash <<< | "sort -n" }
awk: illegal statement at source line 1
if I run the statement as a command :
cat ~/wordlist | grep surf | awk '{ print length(),$0 | "sort -n" }'
I get the correct output:
...
...
12 hypersurface
12 surfboarding
12 undersurface
12 unsurfeiting
13 subtersurface
What am I doing wrong here?
You said it's working for you, but trust me it's got issues. Re-write it as:
awk -v i="$1" '$0 ~ i{print length(), $0 }' | sort -n

Resources