Doing 2 functions through loop in one pass - bash

I've developed a bash script to do some network scanning. However, I'd like to improve the functionality by making it do 2 scans at once. My code looks like this:
for d in `seq 0 255` ;
do
echo 17.6.3.$d
sudo nmap -pT:80,22 17.4.1.$d
done
So at the moment it scans all IP addresses in the subnet /24, 1 by 1 and in order. I'd like some help to make it scan in pairs, so 17.6.3.1 and 17.6.3.2 at the same time, then 17.6.3.3 and 17.6.3.4 and so on until 255. Thanks.

From bash hackers wiki:
for((x = 0; x < 256; x += 2)); do
echo 17.6.3.$x
echo 17.6.3.$((x+1))
# etc.
done

This will do the same:
seq 0 255 | parallel -j2 echo 17.6.3.{}\; sudo nmap -pT:80,22 17.4.1.{}
Personally I would do this:
parallel -j200 --tag sudo nmap -pT:80,22 ::: 17.4.1.{1..254}

Related

How to run command in parallel way within a shell on a single ssh connection in a for loop

I am running a for loop around 3000 volumes within a ssh connection on a storage Server where this runs in a loop one by one, whereas i want the command vol show-footprint "$vols" -fields volume-blocks-footprint,volume-blocks-footprint-bin0,volume-blocks-footprint-bin1 to run parallel over multiple volumes at a time, lets say run it at 10 volumes in a go.
Here myTotalVol contains all 3k volume names like below:
myvol001
myvol002
myvol003
myvol004
myvol005
Below is the small for loop which is working.
for vols in $(cat myTotalVol);
do
echo -n "$vols " ;\
ssh storageServer01 "row 0; set -unit MB; \
vol show-footprint "$vols" -fields volume-blocks-footprint,volume-blocks-footprint-bin0,volume-blocks-footprint-bin1"; \
done
Please suggest if I can run the mentioned command over multiple volumes at a time which are kept in myTotalVol file.
Edit:
As asked by Mark Setchell in the comment section, hence below is just a view how its working ...
$ ssh store01
Last login time: 6/30/2022 10:49:41
store01::> row 0;set -unit MB
(rows)
store01::> vol show-footprint myvol001 -fields volume-blocks-footprint,volume-blocks-footprint-bin0,volume-blocks-footprint-bin1
vserver volume volume-blocks-footprint volume-blocks-footprint-bin0 volume-blocks-footprint-bin1
-------- -------------------- ----------------------- ---------------------------- ----------------------------
myvol001 myvol00198703MB 48272MB 51988MB
as you see the command vol show-footprint myvol001 -fields volume-blocks-footprint,volume-blocks-footprint-bin0,volume-blocks-footprint-bin1 here, i have to run this command over 3000 Volumes like i have myvol001 in this command so, myvol001 will go into the variable like i am using into the for loop and there i am using "$vols" which are referring to 3k vols from a file.
I'm not sure exactly what you are driving at, but you should be able to make a compound statement that generates the commands you want and then send that via ssh like this:
{ printf "row 0; set -unit MB;\n"
while read -r vol ; do
printf "vol show-footprint ${vol} -fields volume-blocks-footprint,volume-blocks-footprint-bin0,volume-blocks-footprint-bin1\n"
done < myTotalVol } | ssh store01
You can try it out and see what it produces if you put a comment character before the | like this:
{ ...
...
done < myTotalVol } # | ssh store01
Or you can do it with awk:
awk 'BEGIN{print "row 0; set -unit MB"} {print "vol show-footprint", $1, "-fields volume-blocks-footprint,volume-blocks-footprint-bin0,volume-blocks-footprint-bin1"}' myTotalVol | ssh store01
Again, put # in front of | ssh store01 in order to see and check the output without sending it to ssh.

What's the difference between these two bash parallelization syntax?

Value "4" below is the number of CPU threads. Idea is to run the tasks in batch of 4 and wait until the current batch is finished before starting the next batch.
Syntax 1:
while read something; do
((++i%4==0)) && wait
(
task using something as input;
)
done < input_file.txt
Syntax 2:
while read something; do
((i=i%4)); ((i++==0)) && wait
(
task using something as input;
)
done < input_file.txt
To me they both work the same except the second one is longer. But when running in the cloud (AWS ubuntu 14.04), only syntax 1 worked. The syntax2 threw a generic syntax error at "((i=i%4));" step and it became a mystery.
"The second one is longer" doesn't help since you used pseudocode.
Maybe this will help:
while read x; do ((i=++i%4)) || wait; sleep $x & done < input_file.txt
My input_file.txt:
10
9
8
7
6
5
4
3
2
1

Bash Scripting : How to loop over X number of files, take input and write to a file in the same line

So I have a program written in C that takes in some parameters: calling it allcell
some sample parameters: -m 1800 -n 9
the files being analyzed: cfdT100-0.trj, cfdT100-1.trj, cfdT100-2.trj, cfdT100-3.trj, ... cfdT100-19.trj
file being fed: template.file
out file: result.file
$ allcell -m 1800 -n 9 cfdT100-[0-19].trj < template.file > result.file
But when I htop, I see that only cfdT100-0.trj, cfdT100-1.trj and cfdT100-9.trj are being read. How do I make the shell read all the files from 0-19 ?
Additionally, when I write a script file to automate this, how should I enclose the line? Will this work:
"$($ allcell -m 1800 -n 9 cfdT100-[0-19].trj < template.file > result.file)"
I believe you want to change your glob expression to cfdT100-{0..19}.trj instead.
neech#nicolaw.uk:~ $ echo cfdT100-{0..19}.trj
cfdT100-0.trj cfdT100-1.trj cfdT100-2.trj cfdT100-3.trj cfdT100-4.trj cfdT100-5.trj cfdT100-6.trj cfdT100-7.trj cfdT100-8.trj cfdT100-9.trj cfdT100-10.trj cfdT100-11.trj cfdT100-12.trj cfdT100-13.trj cfdT100-14.trj cfdT100-15.trj cfdT100-16.trj cfdT100-17.trj cfdT100-18.trj cfdT100-19.trj
Your quoting on the scripted version looks acceptable. Just change the glob.
use recursion function for infinite loop
a()
{
echo "apple"
a
}
a
This the will make a infinite loop

Is it possible to run two loops at the same time?

So I have a project in my cyber security class to make a bash game. I like to make one of those medieval games where you make farms and mines to get resources. Well I like to make something like that. To do that I have to have two while loops running. Like this
while [ blah ]; do
blah
done
while [ blah ]; do
blah
done
Is it possible to run two while loops at the same time and if I am writing it wrong how do I write it?
If you put a & after each done, like done&, you will create new processes in the background that run the while loops. You will have to be careful to realize what this means though, since the bash script will continue executing commands after creating those new processes even if they are not finished. You might use the wait command to prevent this from happening, but I'm not too used to using that so I cannot vouch for it.
Yes, but you will have to fork a new process for each while loop to be executing in. Technically, they won't both run at the same time (unless you consider multiple cores, but this isn't even garaunteed).
Below is a link to how to fork multiple processes using bash.
Forking / Multi-Threaded Processes | Bash
Since you mention this is a school project, I'll stop here lest I help you "not learn".
R
First things first, wrap the loop into a function and then fork it.
This is done when you want to split a process, for example, if I'm processing a CSV with 160,000+ lines, single process/"thread" will take hours. If you wrap the loop into a function and simply fork it, you will have x amount of processes running, then add wait/kill defunct process loop and you are done. here what you are looking at.
while loop with nested loop:
function jobA() {
while read STR;
do
touch $1_temp
key=$(IFS="|";set -- $STR; echo $1)
for each in ${blah[#]};
do
#echo "$each"
done
done <$1;
}
for i in ${blah[#]};
do
echo "$i"
$(jobRDtemp $i) &
child_pid=$!
parent_pid=$$
PIDS+=($child_pid)
echo "forked process $child_pid with parent $parent_pid"
done
for pid in ${PIDS[#]};
do
wait $pid
done
echo "all jobs done"
sleep 1
Now this is wrapped, here is example of a FORKED loop. this means you will have parallel processes run in the background, WAIT will wait for ALL to complete before proceeding. This is important for some type of scripts.
Also, DO NOT use nested FOR loops written C style like presented above, example:
for (( i = 1; i <= 5; i++ )) ### Outer for loop ###
This is VERY slow. use THIS type:
for each in ${blah[#]};
do
#echo "$each"
if [ "$key" = "$each" ]; then
# echo "less than $keyValNeed..."
echo $STR >> $1_temp
fi
done
You could also use nested for loops
for (( i = 1; i <= 5; i++ )) ### Outer for loop ###
do
for (( j = 1 ; j <= 5; j++ )) ### Inner for loop ###
do
echo -n "$i "
done
echo "" #### print the new line ###
done
EDIT: I thought you meant Nested Loop but reading again you said running both loops "at the same time". I will leave my answer here though.

How can I call GAP functions from a shell script?

I want to get the result of a function of the GAP software. This is an interactive command line tool mainly for mathematician who work on group theory related topics.
The documentation/faq states about 8.1: Can I call GAP functions from another programme? that it is in general not possible. However, running GAP as a child process and communicate with it using pipes, pseudo-ttys, UNIX FIFOs or some similar device it can be done.
An example session using a package called CrystCat (Crystallographic Groups Catalog) looks like:
$ gap
gap > LoadPackage( "CrystCat" );
gap > DisplaySpaceGroupType( "P1" );
#I Space-group type (3,1,1,1,1); IT(1) = P1; orbit size 1; fp-free
gap > quit;
$ # exited 'gap' and back in my shell
As I am not familiar with these techniques, can someone show me a minimal example having following functionality:
$ ./script.sh "P1"
#I Space-group type (3,1,1,1,1); IT(1) = P1; orbit size 1; fp-free
$
UPDATE: The accepted answer of this question doesn't work.
Answer by gap-support (using stdin read-in capability of gap)
#!/bin/sh
if [ "$#" != "1" ]; then
echo "Usage: test.sh <string>"
exit 1
fi;
gap -r -b -q << EOI
LoadPackage( "CrystCat" );
DisplaySpaceGroupType( "$1" );
EOI
It works exactly as asked, namely
$ ./script.sh P1
#I Space-group type (3,1,1,1,1); IT(1) = P1; orbit size 1; fp-free

Resources