LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 06-21-2010, 07:14 PM   #1
buee
Member
 
Registered: May 2009
Posts: 81

Rep: Reputation: 16
Trying to make a script to simply output text


This is what I have:

Code:
#!/bin/bash

# This script will go through the billing text file and put Firewall rules in the MikroTik firewall to redirect all traffic to our internal site

billingport="80"
torrentport="81"
speedtestport="82"
webaddress="10.0.0.25"

rm -f /media/32GB/MikroTik/firewall\ rules.txt

# Billing Rules
while read $line; do
	ip=$(cat $line | cut -f2)
	name=$(cat $line | cut -f1)
	echo "/ip firewall nat add chain=dstnat action=dst-nat to-addresses=$webaddress to-ports=$billingport protocol=tcp src-address=$ip dst-port=1-65535 comment=\"$name NONPAYER\"" >> /media/32GB/MikroTik/firewall\ rules.txt
done < "/media/32GB/MikroTik/CustomerUnpaid.txt"
Code:
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=10.0.0.25 to-ports=80 protocol=tcp src-address=192.168.10.45
192.168.10.46
192.168.10.49
192.168.10.50
192.168.10.51
192.168.10.55
192.168.10.56
192.168.10.58 dst-port=1-65535 comment=" NONPAYER"
But what I need is one line per IP address. That, and I can't seem to figure out why $name doesn't populate. Like this:

Code:
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=10.0.0.25 to-ports=80 protocol=tcp src-address=192.168.10.45 dst-port=1-65535 comment="Watson NONPAYER"
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=10.0.0.25 to-ports=80 protocol=tcp src-address=192.168.10.46 dst-port=1-65535 comment="Watson NONPAYER"
Here's the file that it's based off of:

Code:
Baer	192.168.10.44	00:00:00:00:00:00

Watson	192.168.10.45	00:00:00:00:00:01

Watson	192.168.10.46	00:00:00:00:00:02

Smith	192.168.10.49	00:00:00:00:00:05

Johnson	192.168.10.50	00:00:00:00:00:06

Johnson	192.168.10.51	00:00:00:00:00:07

Smith	192.168.10.55	00:00:00:00:00:11

Smith	192.168.10.56	00:00:00:00:00:12

Smith	192.168.10.58	00:00:00:00:00:14
Obviously, it goes name, IP, and MAC. Any clues? I've been working on this for a while trying to get it to output properly but it's not working.

Last edited by buee; 06-21-2010 at 07:16 PM.
 
Old 06-22-2010, 12:34 AM   #2
evo2
LQ Guru
 
Registered: Jan 2009
Location: Japan
Distribution: Mostly Debian and Scientific Linux
Posts: 5,753

Rep: Reputation: 1288Reputation: 1288Reputation: 1288Reputation: 1288Reputation: 1288Reputation: 1288Reputation: 1288Reputation: 1288Reputation: 1288
The main thing that comes to mind here is that cut is very particular about what delimits fields: I think it expects tabs by default. You might find awk more useful in this case. In fact you could write the whole thing in one line of awk. Please post back if you are interested in trying this.

The other problem seems to be:
Code:
while read $line ; do
Should be
Code:
while read line ; do
Cheers,

Evo2.
 
Old 06-22-2010, 12:58 AM   #3
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,425

Rep: Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826
I would just change the whole thing to an awk script, something like:
Code:
#!/usr/bin/awk -f

BEGIN{
    billingport="80"
    torrentport="81"
    speedtestport="82"
    webaddress="10.0.0.25"
    rules="/media/32GB/MikroTik/firewall\ rules.txt"

    print | "rm -v "rules
}

{
print "/ip firewall nat add chain=dstnat action=dst-nat to-addresses="webaddress" to-ports="billingport" protocol=tcp src-address="$2" dst-port=1-65535 comment=\""$1" NONPAYER\" >>"rules
}
Untested, but you get the idea

Last edited by grail; 06-22-2010 at 08:23 PM.
 
Old 06-22-2010, 07:03 PM   #4
buee
Member
 
Registered: May 2009
Posts: 81

Original Poster
Rep: Reputation: 16
Moving in the right direction

Quote:
Originally Posted by evo2 View Post
The main thing that comes to mind here is that cut is very particular about what delimits fields: I think it expects tabs by default. You might find awk more useful in this case. In fact you could write the whole thing in one line of awk. Please post back if you are interested in trying this.

The other problem seems to be:
Code:
while read $line ; do
Should be
Code:
while read line ; do
Cheers,

Evo2.
So I did this and with a little tweak, I managed to get it to output ALMOST the way it needs to be. I do get it processing line by line and outputting one line per IP address/Name, but it's putting the WHOLE line as the variable so I get output like this:

Code:
/ip firewall nat add chain=dstnat action=dst-nat to-addresses=10.0.0.25 to-ports=80 protocol=tcp src-address=Smith 192.168.10.58 00:00:00:00:00:14
 dst-port=1-65535 comment="Smith 192.168.10.58 00:00:00:00:00:14
 NONPAYER"
To answer both questions about sed and awk, to be honest, they worry me. Whenever I post something on a forum, I get a response that includes awk and sed, I just get the command, no explanation. So truthfully, I don't know either and I don't have time right now to learn it. If those variable assignments could be done easily with either sed or awk, I'd be more than happy to throw the necessary command in there, I just don't know the necessary command lol.
 
Old 06-22-2010, 07:26 PM   #5
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,332
Blog Entries: 55

Rep: Reputation: 3533Reputation: 3533Reputation: 3533Reputation: 3533Reputation: 3533Reputation: 3533Reputation: 3533Reputation: 3533Reputation: 3533Reputation: 3533Reputation: 3533
Quote:
Originally Posted by buee View Post
So I did this and with a little tweak
What tweak? Posting back code helps.

This works too:
Code:
#!/bin/sh --
billingport="80"
torrentport="81"
speedtestport="82"
webaddress="10.0.0.25"

cat /path/to/logfile | while read LUSER LIP LMAC; do
        [ ${#LUSER} -eq 0 ] || echo "/ip firewall nat add chain=dstnat action=dst-nat to-addresses=$webaddress \
to-ports=$billingport protocol=tcp src-address=${LIP} dst-port=1-65535 comment=\"${LUSER} NONPAYER\""
done
exit 0
 
Old 06-22-2010, 07:57 PM   #6
buee
Member
 
Registered: May 2009
Posts: 81

Original Poster
Rep: Reputation: 16
Quote:
Originally Posted by unSpawn View Post
What tweak? Posting back code helps.

This works too:
Code:
#!/bin/sh --
billingport="80"
torrentport="81"
speedtestport="82"
webaddress="10.0.0.25"

cat /path/to/logfile | while read LUSER LIP LMAC; do
        [ ${#LUSER} -eq 0 ] || echo "/ip firewall nat add chain=dstnat action=dst-nat to-addresses=$webaddress \
to-ports=$billingport protocol=tcp src-address=${LIP} dst-port=1-65535 comment=\"${LUSER} NONPAYER\""
done
exit 0
Code:
while read line; do
	ip=$(echo $line | cut -f2)
	name=$(echo $line | cut -f1)
That's it. I was getting cat errors so I changed it to echo. Which I'm sure is why I'm getting the whole line in to the variable, not sure why cut isn't working for me though. It's usually worked in the past when avoiding sed and awk ;-)
 
Old 06-22-2010, 08:23 PM   #7
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,425

Rep: Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826
Well I am happy to explain if you have any questions about the awk script
 
Old 06-22-2010, 09:20 PM   #8
buee
Member
 
Registered: May 2009
Posts: 81

Original Poster
Rep: Reputation: 16
Quote:
Originally Posted by grail View Post
Well I am happy to explain if you have any questions about the awk script
lol talking about setting yourself up. I get the variable assignments, but I don't get anything after that.

Code:
    print | "rm -v "rules
}

{
print "/ip firewall nat add chain=dstnat action=dst-nat to-addresses="webaddress" to-ports="billingport" protocol=tcp src-address="$2" dst-port=1-65535 comment=\""$1" NONPAYER\" >>"rules
}
Basically from "rm -v is where I get lost.
 
Old 06-22-2010, 10:18 PM   #9
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,425

Rep: Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826
No probs:

Quote:
print | "rm -v "rules
Simply put, by placing the pipe after the print command allows the following text to be executed by the shell.
So this equates to the same as the following on the command line:
Code:
rm -v /media/32GB/MikroTik/firewall\ rules.txt
Quote:
print "/ip firewall nat add chain=dstnat action=dst-nat to-addresses="webaddress" to-ports="billingport" protocol=tcp src-address="$2" dst-port=1-65535 comment=\""$1" NONPAYER\" >>"rules
Again nothing really tricky here, there are a number of variable substitutions and the end redirects the output to the new file that you removed in the item explained above.
I will assume that you follow all the variable name inputs, so the ones left to explain are as follows:

$1 = First field from your input file which is the name, ie first one being Baer

$2 = Second field from input file which is ip address, ie again first one being 192.168.10.44

>>"rules = output to /media/32GB/MikroTik/firewall\ rules.txt as appending information

Let me know if you have any other queries?
 
Old 06-23-2010, 02:38 AM   #10
konsolebox
Senior Member
 
Registered: Oct 2005
Distribution: Gentoo, Slackware, LFS
Posts: 2,248
Blog Entries: 8

Rep: Reputation: 235Reputation: 235Reputation: 235
We can also do it this way:
Code:
while read name_ ip mac; do
    if [[ -n $name_ && -n $ip && -n $mac ]]; then
        # do something with $name_, $ip and $mac
    fi
done < filepath.txt
By the way, $name might be a reserved variable or something that made a bug in earlier versions of bash so better not use it.
 
Old 06-24-2010, 11:25 PM   #11
buee
Member
 
Registered: May 2009
Posts: 81

Original Poster
Rep: Reputation: 16
Errors

Quote:
Originally Posted by grail View Post
No probs:


Simply put, by placing the pipe after the print command allows the following text to be executed by the shell.
So this equates to the same as the following on the command line:
Code:
rm -v /media/32GB/MikroTik/firewall\ rules.txt


Again nothing really tricky here, there are a number of variable substitutions and the end redirects the output to the new file that you removed in the item explained above.
I will assume that you follow all the variable name inputs, so the ones left to explain are as follows:

$1 = First field from your input file which is the name, ie first one being Baer

$2 = Second field from input file which is ip address, ie again first one being 192.168.10.44

>>"rules = output to /media/32GB/MikroTik/firewall\ rules.txt as appending information

Let me know if you have any other queries?
So I copied the script directly from the site and added two more sections as they're part of the original script. I figured if I saw how to do part A, and B & C are the same, I now have a template. Problem is now I'm getting errors. As I said, I don't know awk from a hole in the wall so I don't really know how to figure these errors out. Here's what I get for errors:

Code:
./Billing.sh: line 38: BEGIN{: command not found
./Billing.sh: line 45: rm -v rules: command not found
./Billing.sh: line 46: syntax error near unexpected token `}'
./Billing.sh: line 46: `}'
And here is the script that was executed:

Code:
#!/usr/bin/awk -f

BEGIN{
    billingport="80"
    torrentport="81"
    speedtestport="82"
    webaddress="10.0.0.25"
    rules="/media/32GB/MikroTik/firewall\ rules.txt"

    print | "rm -v "rules
}

#Billing
{
print "/ip firewall nat add chain=dstnat action=dst-nat to-addresses="webaddress" to-ports="billingport" protocol=tcp src-address="$2" dst-port=1-65535 comment=\""$1" NONPAYER\" >>"rules
}

#Torrents
{
print "/ip firewall nat add chain=dstnat action=dst-nat to-addresses="webaddress" to-ports="torrentport" protocol=tcp src-address="$2" dst-port=1-65535 comment=\""$1" TORRENTER\" >>"rules
}

#Speed Test
{
print "/ip firewall nat add chain=dstnat action=dst-nat to-addresses="webaddress" to-ports="speedtestport" protocol=tcp src-address="$2" dst-port=1-65535 comment=\""$1" SPEED JUNKIE\" >>"rules
}

exit 0
 
Old 06-24-2010, 11:31 PM   #12
buee
Member
 
Registered: May 2009
Posts: 81

Original Poster
Rep: Reputation: 16
So I took some spaces out of file names and I've widdled it down to this:

Code:
rm: cannot remove `/media/32GB/MikroTik/firewall_rules.txt': No such file or directory
Then it just chills there for a Ctrl+C

Then it dawned on me, where is it getting the variables $1 and $2? There's nothing specifying a file to pull from in the script at all. Am I retarded?
 
Old 06-25-2010, 01:17 AM   #13
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,425

Rep: Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826Reputation: 2826
Ok ... so good to see you are experimenting

Firstly, here is a really good reference to help you: www.gnu.org/manual/gawk/html_node/index.html

Now, lets have a look at some of your errors / issues (which by the way I noticed I created one - oops) and other things not required:

1. exit 0 - not required at least not where you have it as this is not a bash script but an awk one

2. Not sure how you are getting any of the following errors as the code you have posted is only 28 lines long???
Quote:
./Billing.sh: line 38: BEGIN{: command not found
./Billing.sh: line 45: rm -v rules: command not found
./Billing.sh: line 46: syntax error near unexpected token `}'
./Billing.sh: line 46: `}'
3. Repetition Repetition, lets not go nuts and write the same thing, especially a long thing, so many times:
Code:
output="/ip firewall nat add chain=dstnat action=dst-nat to-addresses="webaddress" to-ports="speedtestport" protocol=tcp src-address="$2" dst-port=1-65535 comment=\""$1

#Billing
print output" NONPAYER\">>rules
#Torrents
print output" TORRENTER\">>rules
#Speed Test
print output" SPEED JUNKIE\">>rules
So unless you change any of the items in the output string this should work. Also note how the append has been changed to go to 'rules' .... this was my typo.

4. Sorry, but yes I should have mentioned that the script is run as follows:
Code:
./script_name input_file
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Make a script that uses the output from another script as the variables? Oakems Programming 11 06-18-2009 06:21 PM
remote secure shell script text output aral Programming 6 09-02-2006 11:01 PM
Bash script- capture cdparanoia text output code-breaker Linux - Software 7 08-03-2006 11:13 PM
How do I make PHP display output from my shell script? farmerjoe Programming 2 04-03-2005 02:15 PM
bash-script: output text between two ocurrences of a specific string isl01jbe Programming 1 06-17-2004 03:36 PM


All times are GMT -5. The time now is 10:16 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration