Reading from pasted input with line breaks in a Bash Script - bash

I've been trying for a couple nights to get this Script to run with no luck. I'm trying to write a script using Bash that allows a user to paste a block of text, and the script will grep out the valid IP addresses from the text, and automatically ping them in order.
So far, after much modification, I'm stuck at this point:
#!/bin/sh
echo Paste Text with IP Addresses
read inputtext
echo "$inputtext">inputtext.txt
grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}" inputtext.txt > address.txt
awk '{print $1}' < address.txt | while read ip; do
if ping -c1 $ip >/dev/null 2>&1; then
echo $ip IS UP
else
echo $ip IS DOWN
fi
done
rm inputtext.txt
rm address.txt
After running this script, the user is prompted as desired, and if an IP address was included in the first line of text, the ping check will succeed, but then all the text after that line will be spat out onto the following command prompt. So it seems that my issue lies in when I read from user input. The only part that is being read is the first line, and once a break is encountered, the script does not considered any lines past the first in its work.

As written, you just need an outer loop to actually read each line of user input.
#!/bin/sh
echo Paste Text with IP Addresses
while read -r inputtext
do
echo "$inputtext">inputtext.txt
grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}" inputtext.txt > address.txt
awk '{print $1}' < address.txt | while read ip; do
if ping -c1 $ip >/dev/null 2>&1; then
echo $ip IS UP
else
echo $ip IS DOWN
fi
done
rm inputtext.txt
rm address.txt
done
However, you can actually simplify this much further and eliminate the temporary files.
#!/bin/sh
echo Paste Text with IP Addresses
while read -r inputtext
do
ip=$(echo "$inputtext" | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}" | awk '{print $1}')
if ping -c1 $ip >/dev/null 2>&1; then
echo $ip IS UP
else
echo $ip IS DOWN
fi
done

Related

Loop EOF ssh -n can't create file

Hope this time it's not a duplicate. I didn't find anything.
My code:
#!/bin/bash
FILE=/home/user/srv.txt
TICKET=task
while read LINE; do
ssh -nT $LINE << 'EOF'
touch info.txt
hostname >> info.txt
ifconfig | grep inet | awk '$3 ~ "cast" {print $2}' >> info.txt
grep -i ^server /etc/zabbix/zabbix_agentd.conf >> info.txt
echo "- Done -" >> info.txt
EOF
ssh -nT $LINE "cat info.txt" >> $TICKET.txt
done < $FILE #End
My issue:
if I only use ssh $LINE it will only ssh to the host on the first line and also display an error Pseudo-terminal will not be allocated because stdin is not a terminal.
using ssh -T , fix the error message above and it will create the file info.txt
using ssh -nT , fix the error where ssh only read the first line but I get an error message cat: info.txt: No such file or directory. If I ssh to the hosts, I can confirm that there is no info.txt file in my home folder. and with ssh -T, I have this file in my home folder.
I tried with the option -t, also HERE, EOF without ' ... ' but no luck
Do I miss something?
Thanks for your help,
Iswaren
You have two problems.
If you invoke ssh without -n it may consume the $FILE input (it drains its stdin)
If you invoke ssh with -n it won't read its stdin, so none of the commands will be executed
However, the first ssh has had its input redirected to come from a heredoc, so it does not need -n.
As stated in the comments, the second ssh call is not needed. Rather than piping into info.txt and then copying that into a local file, just output to the local file directly:
while read LINE; do
ssh -T $LINE >>$TICKET.txt <<'EOF'
hostname
ifconfig | grep inet | awk '$3 ~ "cast" {print $2}'
grep -i ^server /etc/zabbix/zabbix_agentd.conf
echo "- Done -"
EOF
done <$FILE

netcat inside a while read loop returning immediately

I am making a menu for myself, because sometimes I need to search (Or NMAP which port).
I want to do the same as running the command in the command line.
Here is a piece of my code:
nmap $1 | grep open | while read line; do
serviceport=$(echo $line | cut -d' ' -f1 | cut -d'/' -f1);
if [ $i -eq $choice ]; then
echo "Running command: netcat $1 $serviceport";
netcat $1 $serviceport;
fi;
i=$(($i+1));
done;
It is closing immediately after it scanned everything with nmap.
Don't use FD 0 (stdin) for both your read loop and netcat. If you don't distinguish these streams, netcat can consume content emitted by the nmap | grep pipeline rather than leaving that content to be read by read.
This has a few undesirable effects: Further parts of the while/read loop don't get executed, and netcat sees a closed stdin stream and exits when the pipeline's contents are consumed (so you don't get interactive control of netcat, if that's what you're trying to accomplish). An easy way to work around this issue is to feed the output of your nmap pipeline in on a non-default file descriptor; below, I'm using FD 3.
There's a lot wrong with this code beyond the scope of the question, so please don't consider the parts I've copied-and-pasted an endorsement, but:
while read -r -u 3 line; do
serviceport=${line%% *}; serviceport=${serviceport##/*}
if [ "$i" -eq "$choice" ]; then
echo "Running command: netcat $1 $serviceport"
netcat "$1" "$serviceport"
fi
done 3< <(nmap "$1" | grep open)

crash do while with ssh ls

Script read file line by line and check folders on remote server using command ls
But my do-while - is work only 1 time, and ; for example: if try use rsync - all fine, while work correct, problem only with ssh user#server ls $SERVER_FOLDER >> $LOG
i try use incorrect syntax?
Error from console: syntax error near unexpected token 'done'
LOG="/path_to_log/log.txt"
FILE="/path_to_file/projects_id.txt"
cat $FILE | while read -r line || [[ -n $line ]]
do
ID=$(echo $line | cut -d' ' -f3)
SERVER_FOLDER=`echo "/path_to_id/$ID/"`
echo "SERVER_FOLDER:" $SERVER_FOLDER
ssh user#server ls $SERVER_FOLDER >> $LOG
sleep 20
done
Add the -n option to ssh to prevent it from reading stdin. What is happening is that ssh is consuming all the input from the file (that is coming through stdin), so the while loop terminates after the first line because there is nothing left for it to read.
Change your code to:
while read -r line || [[ -n $line ]]
do
ID=$(cut -d' ' -f3 <<< "$line")
SERVER_FOLDER="/path_to_id/$ID/"
echo "SERVER_FOLDER: $SERVER_FOLDER"
ssh -n user#server ls $SERVER_FOLDER >> $LOG
sleep 20
done < "$FILE"
I have also made some other improvements such as changing the way you are reading the file (cat is not necessary).

bash script to read/ping a list of ip addresses from a text file and then write the results to another file?

I have a text file with a lists of IP addresses called address.txt which contains the following
172.26.26.1 wlan01
172.26.27.65 wlan02
172.26.28.180 wlan03
I need to write a bash script that reads the only IP addresses, ping them and output to a another text file to something like this:
172.26.26.1 IS UP
172.26.27.65 IS DOWN
172.26.28.180 IS DOWN
I am fairly new to bash scripting so I am not sure where to start with this. Any help would be much appreciated.
In Linux this would work:
awk '{print $1}' < address.txt | while read ip; do ping -c1 $ip >/dev/null 2>&1 && echo $ip IS UP || echo $ip IS DOWN; done
I don't have a cygwin now to test, but it should work there too.
Explanation:
With awk we get the first column from the input file and pipe it into a loop
We send a single ping to $ip, and redirect standard output and standard error to /dev/null so it doesn't pollute our output
If ping is successful, the command after && is executed: echo $ip IS UP
If ping fails, the command after || is executed: echo $ip IS DOWN
Somewhat more readable, expanded format, to put in a script:
#!/bin/sh
awk '{print $1}' < address.txt | while read ip; do
if ping -c1 $ip >/dev/null 2>&1; then
echo $ip IS UP
else
echo $ip IS DOWN
fi
done

Bash script only read the first line of the file

I wrote a script to ssh to remote server to find the disk usage of a user. However, this script can only read the first line, it doesn't continue on the other lines of the file. Anything wrong with my script? Thanks.
#!/bin/bash
FILE="myfile.txt"
while read line; do
server=`echo $line|awk '{print $1}'`
cpid=`echo $line|awk '{print $2}'`
echo $server "---" $cpid "---" `ssh $server grep $cpid /var/cpanel/repquota.cache|awk '{print int($3/1000) "MB"}'`
done < $FILE
myfile.txt contents:
server1 user1
server2 user2
server3 user3
The ssh call is inheriting its standard input from the while loop, which redirects from your file. This causes the ssh command to consume the rest of the file. You'll need to use a different file descriptor to supply the read command:
#!/bin/bash
FILE="myfile.txt"
while read -u 3 server cpid; do
printf "$server---$cpid---"
ssh $server "grep $cpid /var/cpanel/repquota.cache | awk '{print int($3/1000) \"MB\"}'"
done 3< $FILE
An alternative is to explicitly redirect input to ssh from /dev/null, since you're not using it anyway.
#!/bin/bash
FILE="myfile.txt"
while read server cpid; do
printf "$server---$cpid---"
< /dev/null ssh $server "grep $cpid /var/cpanel/repquota.cache | awk '{print int($3/1000) \"MB\"}'"
done < $FILE
First of all you can simplify your read loop to
while read server cpid; do
echo $server "---" $cpid "---" `ssh ...`
done <$FILE
and save the parsing with awk. Another simplification is to save the call to grep and let awk do the search for $cpid
ssh $server "awk '/$cpid/ {print int(\$3/1000) \"MB\"}' /var/cpanel/repquota.cache"
To your problem, I guess the ssh call doesn't return, because it waits for a password or something, and so prevents the loop to continue.

Resources