Using pipes in comment executed using Plink from PowerShell - shell

In PowerShell, I use Plink to ssh on to a NetScaler device.
Everything works fine, but it takes a very long time to run the script because of the amount of data downloaded from the remote device to the local machine, where I'm running PowerShell.
Here is the script:
$log = C:\plink.exe -batch -l User -pw PWD 10.1.1.1 "shell "zgrep -oE '\w+\.some\.com' /var/log/ns.log.0.gz""
To improve the performance, I need to reduce the amount of data transferred from the device.
All I need is just the first part of the domain \w+\ so I tried to add | cut –d . –f 1 but I get this:
cut : The term 'cut' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:144
+ ... hell "zgrep -oE '\w+\.some\.com' /var/log/ns.log.0.gz | cut -d . -f ...
+ ~~~
+ CategoryInfo : ObjectNotFound: (cut:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I’ve tried different ways to escape the | and trired putting the command into a variable or in to a file and using the –m switch.
Everything comes out with the same result.
The cut command works fine, when I use PuTTY to ssh to the device.
Is this problem with PowerShell, Plink or both? Can I use the cut command without a pipe? Or is there another way to return just the \w+\ part?
Here's the output from various attempts to get the cut working (not allowed to upload screenshots from work)
PS C:\windows\system32> C:\NetScalerBackup\plink.exe -batch -l $un -pw $pwd $PrimaryNS shell "zgrep -oE '\w+\.some\.com' /var/log/ns.log.0.gz | cut -d . -f1"
Done
^^^
ERROR: No such command
C:\NetScalerBackup\plink.exe : ERROR: No such command
At line:1 char:1
+ C:\NetScalerBackup\plink.exe -batch -l $un -pw $pwd $PrimaryNS shell ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (ERROR: No such command:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
PS C:\windows\system32> C:\NetScalerBackup\plink.exe -batch -l $un -pw $pwd $PrimaryNS "shell `"zgrep -oE '\w+\.some\.com' /var/log/ns.log.0.gz | cut -d . -f1`""
Done
^^^
ERROR: No such command
C:\NetScalerBackup\plink.exe : ERROR: No such command
At line:1 char:1
+ C:\NetScalerBackup\plink.exe -batch -l $un -pw $pwd $PrimaryNS "shell ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (ERROR: No such command:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
PS C:\windows\system32> C:\NetScalerBackup\plink.exe -batch -l $un -pw $pwd $PrimaryNS shell zgrep -oE '\w+\.some\.com' /var/log/ns.log.0.gz | cut -d . -f1
cut : The term 'cut' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:122
+ ... shell zgrep -oE '\w+\.some\.com' /var/log/ns.log.0.gz | cut -d . -f ...
+ ~~~
+ CategoryInfo : ObjectNotFound: (cut:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Update
#Martin:
when I try
"shell `"zgrep -oE '\w+\.some\.com' /var/log/ns.log.0.gz | cut -d . -f1`"`nexit`n" | C:\NetScalerBackup\plink.exe -batch -l $un -pw $pwd $PrimaryNS
I get:
shell "zgrep -oE '\w+\.some\.com' /var/log/ns.log.0.gz | cut -d . -f1"
exit
Done
> shell "zgrep -oE '\w+\.some\.com' /var/log/ns.log.0.gz | cut -d . -f1"
grep: unknown directories method
ERROR:
> exit
Bye!
If I take out the back-tick Quotes (`")
"shell zgrep -oE '\w+\.some\.com' /var/log/ns.log.0.gz | cut -d . -f1`nexit`n" | C:\NetScalerBackup\plink.exe -batch -l $un -pw $pwd $PrimaryNS
This is the response:
Done
> shell zgrep -oE '\w+\.aramco\.com' /var/log/ns.log.0.gz | cut -d . -f1
^^^
ERROR: No such command
> exit
Bye!

The outer quotes are not needed by Plink and just complicate parsing. This should work:
$log = C:\plink.exe -batch -l User -pw PWD 10.1.1.1 shell "zgrep -oE '\w+\.some\.com' /var/log/ns.log.0.gz | cut -d . -f"
If you want to keep the outer quotes, you have escape the inner quotes:
$log = C:\plink.exe -batch -l User -pw PWD 10.1.1.1 "shell `"zgrep -oE '\w+\.some\.com' /var/log/ns.log.0.gz | cut -d . -f`""

Related

quoting in bash with ssh and grep

I don't get why this doesn't work:
filesToInclude="$(ssh -t $host ls -t /var/log/*.LOG | sort | egrep -A6 "$LastBootUp" | tr '\n' '[:space:]' | tr -s [:space:] ' ')"
allALL="$( ssh $host grep -Ev "$excludeSearch" $filesToInclude )"
on another server, which is capable of ag this works totally fine.
if I copy the output of filesToInclude to $filesToInclude manually, it works.
that is the output:
grep: o such file or directory
bash: 0m/var/log/A-MINI_23311_H007164M49_220419_1906_XX.LOG: No such file or directory

ssh remote command execution quoting and piping awk

I'm working on a script, that should find certain disks and add hostname to them.
I'm using this for 40 servers with a for loop in bash
#!/bin/bash
for i in myservers{1..40}
do ssh user#$i findmnt -o SIZE,TARGET -n -l |
grep '1.8T\|1.6T\|1.7T' |
sed 's/^[ \t]*//' |
cut -d ' ' -f 2 |
awk -v HOSTNAME=$HOSTNAME '{print HOSTNAME ":" $0}'; done |
tee sorted.log
can you help out with the quoting here? It looks like awk gets piped (hostname) from localhost, not the remote server.
Everything after the first pipe is running locally, not on the remote server.
Try quoting the entire pipeline to have it run on the remote server:
#!/bin/bash
for i in myservers{1..40}
do ssh user#$i "findmnt -o SIZE,TARGET -n -l |
sed 's/^[ \t]*//' |
cut -d ' ' -f 2 |
awk -v HOSTNAME=\$HOSTNAME '{print HOSTNAME \":\" \$0}'" ;
done | tee sorted.log
This is a shorter version of your stuff:
findmnt -o SIZE,TARGET -n -l |
awk -v HOSTNAME=$HOSTNAME '/M/{print HOSTNAME ":" $2}'
Applied to the above:
for i in myservers{1..40}
do ssh user#$i bash -c '
findmnt -o SIZE,TARGET -n -l |
awk -v HOSTNAME=$HOSTNAME '"'"'/M/{print HOSTNAME ":" $2}'"'"' '
done |
tee sorted.log
see: How to escape the single quote character in an ssh / remote bash command?

Copying data from one linux machine to another

I am trying to run a script placed in machine A ,in machine B .
This script generates a output file F.
Then I am trying to copy this File F back to machine A .
The command I am using to run the .sh placed in machine A is
ssh root#Machine B 'bash -s' < test.sh
The contents of the file "test.sh" (which generates the output and tried to copy it back ) are .
#!/bin/bash
memory=$(cat /proc/meminfo | grep 'MemTotal' | awk -F ':' '{print$2}')
processor=$(lscpu | grep 'CPU(s):'|awk -F ':' '{print$2}'|head -1)
socket=$(lscpu | grep 'Socket(s):'|awk -F ':' '{print$2}')
cores=$(lscpu | grep 'Core(s) per socket'|awk -F ':' '{print$2}')
cpuspeed=$(lscpu | grep 'CPU MHz'|awk -F ':' '{print$2}')
echo $memory,$processor,$socket,$cores,$cpuspeed >>server_info.txt
/usr/bin/expect <<EOF
spawn scp /path/server_info.txt root#MachineA:/path/
expect "Password: "
send "pwd\r"
EOF
The whole thing together is not working ,for some reason . What am I doing wrong here

Scape quotes on remote command

I'm try to pass a commadn on remote server.
Command work fine on local server, but when try pass on remote server trought ssh get error for bad scpaing
ls -t /root/mysql/*.sql | awk 'NR>2 {system(\"rm \"" $0 \"\"")}'
Full comnand
ssh root#host -p XXX "mysqldump --opt --all-databases > /root/mysql/$(date +%Y%m%d%H%M%S).sql;ls -t /root/mysql/*.sql | awk 'NR>2 {system(\"rm \"" $0 \"\"")}'"
Actually no need to use awk and avoid all that quotes escaping:
ls -t /root/mysql/*.sql | tail -n +1 | xargs rm
This is assuming your *.sql files don't have any whitespaces otherwise you should use stat command and sort the output using sort.

Generating bash script arrays with elements containing spaces from commands

I have a script that logs in to a remote host to pull a directory listing to later present options to the user. It was all working perfectly, until some of the directories started having spaces in them. I have tried several syntaxes and googled the life out of this and I am now at the end of my tether. The original command was this:
SERVERDIRS=($(sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -l --time-style="long-iso" $FROMFOLDER | egrep '^d' | awk '{print $8}'))
I first off changed this code to be able to read the spaces like this:
SERVERDIRS=($(sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -l --time-style="long-iso" $FROMFOLDER | egrep '^d' | cut -d' ' -f8-))
However This resulted in each word being recognised as a variable. I have tried many ways to try to solve this, two of which were:
SERVERDIRS=($(sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -d $FROMFOLDER* |rev| cut -d'/' -f1|rev|sed s/^/\"/g|sed s/$/\"/g))
SERVERDIRS=($(sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -d $FROMFOLDER* |rev| cut -d'/' -f1|rev|sed 's/ /\\ /g'))
SERVERDIRS=(`sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -d $FROMFOLDER* |rev| cut -d'/' -f1|rev|sed 's/ /\\ /g'`)
How can I resolve these directories in to separate elements correctly?
If you're trying to read one array value per line instead of space-separated, then $() syntax won't help. Try readarray (Bash 4):
readarray SERVERDIRS < <(sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -l --time-style="long-iso" $FROMFOLDER | egrep '^d' | cut -d' ' -f8-)
or assign IFS and read with -d, -r, and -a set:
IFS=$'\n' read -d '' -r -a SERVERDIRS < <(sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -l --time-style="long-iso" $FROMFOLDER | egrep '^d' | cut -d' ' -f8-)
or, really, any other answer to this SO question.
If you're unfamiliar with <() syntax, it's known as process substitution and will allow your variable to be set in your current environment rather than the instantly-discarded subshell that a pipe would create.
Bear in mind that this process is a little dangerous; filenames can also contain newlines, so it's usually much preferred to use find ... -print0.
If you only need to list directories, try this
ls -d /usr/local/src/*/
or
ls -d /path/to/your/directory/*/
You can then loop through all directories
#!/bin/bash
aa=`ls -d /usr/local/src/*/`
for dir in "${aa}[#]"
do
echo "$dir"
done
This works if dir names contain spaces.

Resources