How to take each string (hostname) from an output? - linux

I am trying to write a script using bash that performing show command and takes each hostname (string) from the show output and perform action (show command) on it.
For example:
root#Router2:~$ show routers
Hostname1
Hostname2
Hostname3
And i want to take each hostname (hostname 1, hostname 2 and hostname3) and perform action on each one of them.
Here is what i manage to do:
figlet Status code
u=$(tput smul)
b=$(tput bold)
n=$(tput sgr0)
echo "${b}${u}Enter server's name${n}"
read -e server
echo ""
Routershow$=(show routers)
After that, i want to take each string (hostname) from the $Routershow output. How can i do that?
Thanks

I usually use while read x command where "x" is a variable name:
show routers | while read routerName
do
echo $routerName
done

Use a loop over all items (hostnames) that result from your command (show routers). For example:
for hostname in $(show routers)
do
# access each hostname here. e.g.
echo $hostname
done
or as extension to your script:
...
Routershow=$(show routers)
for hostname in $(echo $Routershow)
do
# access each hostname here. e.g.
echo $hostname
done

Related

Xterm: How can I direct input from one terminal tab to another?

As I am a beginner coder, I apologize in advance for improper terminology.
This is the main script which calls the script ping.sh in a new tab.
#!/bin/bash
echo "The script is running!"
rm ping.txt
echo "Enter your desired IP address:"
read ADDRESS
osascript -e 'tell application "System Events" to tell application "Terminal"
do script "./ping.sh"
end tell'
echo "The script has ended!"
exit 0;
So, as I said the script ping.sh is called now. It goes like this.
#!/bin/bash
echo "Welcome to the new tab!"
ping -c 3 $ADDRESS > ping.txt
exit 0
The problem I have is that the read input from the first tab isn't recognizable in the second tab. Is there a way to solve this? I am probably missing a linking constructor or something like that. Please help!
I have no idea what osascript is, or how it works, but it might be helpful to know that shell scripts can access command line arguments with the special variables $1, $2, $3, etc.
This means you can rewrite your ping.sh script like so:
#!/bin/bash
echo "Welcome to the new tab!"
ping -c 3 "$1" > ping.txt
exit 0
And then call it like so:
#!/bin/bash
echo "Enter your desired IP address:"
read ADDRESS
./ping.sh "$ADDRESS"
Otherwise, to make sure subsequent commands have access to the same environment variables, you have to export them. From help export:
export: export [-fn] [name[=value] ...] or export -p
Set export attribute for shell variables.
Marks each NAME for automatic export to the environment of subsequently
executed commands. If VALUE is supplied, assign VALUE before exporting.
To make your original ping.sh work you could do the following:
#!/bin/bash
echo "Enter your desired IP address:"
read ADDRESS
export ADDRESS
./ping.sh

How does one create a wrapper around a program?

I want to learn to create a wrapper around a program in linux. How does one do this? A tutorial reference web-page/link or example will do. To clarify what I want to learn, I will explain with an example.
I use vim for editing text files. And use rcs as my simple revision control system. rcs allows you to check-in and checkout-files. I would like to create a warpper program named vir which when I type in the shell as:
$ vir temp.txt
will load the file temp.txt into rcs with ci -u temp.txt and then allows me to edit the file using vim.
When I get out and go back in, It will need to check out the file first, using ci -u temp.txt and allow me to edit the file as one normally does with vim, and then when I save and exit, it should check-in the file using co -u temp.txt and as part of that I should be able to add a version control comment.
Basically, all I want to be doing on the command line is:
$ vir temp.txt
as one would with vim. And the wrapper should take care of the version control for me.
Take a look at rcsvers.vim, a vim plugin for automatically saving versions in RCS; you could modify that. There are also other RCS plugins for vim at vim.org
I have a wrapper to enhance the ping command (using zsh) it could, maybe help you:
# ping command wrapper - Last Change: out 27 2019 18:47
# source: https://www.cyberciti.biz/tips/unix-linux-bash-shell-script-wrapper-examples.html
ping(){
# Name: ping() wrapper
# Arg: (url|domain|ip)
# Purpose: Send ping request to domain by removing urls, protocol, username:pass using system /usr/bin/ping
local array=( $# ) # get all args in an array
local host=${array[-1]} # get the last arg
local args=${array[1,-2]} # get all args before last arg in $#
#local _ping="/usr/bin/ping"
local _ping="/bin/ping"
local c=$(_getdomainnameonly "$host")
[ "$host" != "$c" ] && echo "Sending ICMP ECHO_REQUEST to \"$c\"..."
# pass args and host
# $_ping $args $c
# default args for ping
$_ping -n -c 2 -i 1 -W1 $c
}
_getdomainnameonly(){
# Name: _getdomainnameonly
# Arg: Url/domain/ip
# Returns: Only domain name
# Purpose: Get domain name and remove protocol part, username:password and other parts from url
# get url
local h="$1"
# upper to lowercase
local f="${h:l}"
# remove protocol part of hostname
f="${f#http://}"
f="${f#https://}"
f="${f#ftp://}"
f="${f#scp://}"
f="${f#scp://}"
f="${f#sftp://}"
# Remove username and/or username:password part of hostname
f="${f#*:*#}"
f="${f#*#}"
# remove all /foo/xyz.html*
f=${f%%/*}
# show domain name only
echo "$f"
}
What it hides the local ping using a function called "ping", so if your script has precedence on your path it will find at first the function ping. Then inside the script I define an internal variable called ping that points out to the real ping command:
local _ping="/bin/ping"
You can also notice that the args are stored in one array.

How can I store the result of this command as a variable in my bash script?

I'm building a simple tool that will let me know if a site "siim.ml" resolves. If I run the command "ping siim.ml | grep "Name or service not known"" in the linux command line then it only returns text if the site does not resolve. Any working site returns nothing.
Using this I want to check if the result of that command is empty, and if it is I want to perform an action.
Problem is no matter what I do the variable is empty! And it still just prints the result to stdout instead of storing it.
I've already tried switching between `command` and $(command), and removed the pipe w/ the grep, but it has not worked
#!/bin/bash
result=$(ping siim.ml | grep "Name or service not known")
echo "Result var = " $result
if ["$result" = ""]
then
#siim.ml resolved
#/usr/local/bin/textMe/testSite.sh "siim.ml has resolved"
echo "It would send the text"
fi
When I run the script it prints this:
ping: siim.ml: Name or service not known
Result var =
It would send the text
It's almost certainly because that error is going to standard error rather than standard output (the latter which will be captured by $()).
You can combine standard error into the output stream as follows:
result=$(ping siim.ml 2>&1 | grep "Name or service not known")
In addition, you need spaces separating the [ and ] characters from the expression:
if [ "$result" = "" ]
Or even slightly more terse, just check whether ping succeeds, e.g.
if ping -q -c 1 siim.ml &>/dev/null
then
echo "It would send the text"
## set result or whatever else you need on success here
fi
This produces no output due to the redirection to /dev/null and succeeds only if a successful ping of siim.ml succeeds.

Bash : how to grep string from file

am having issue with grep as VESTACP is using it a lot.
i have file mysql.conf
HOST='localhost' USER='root' PASSWORD='xxxxxx' CHARSETS='UTF8,LATIN1,WIN1250,WIN1251,WIN1252,WIN1256,WIN1258,KOI8' MAX_DB='500' U_SYS_USERS='' U_DB_BASES='1' SUSPENDED='no' TIME='05:32:47' DATE='2016-03-20'
now when i run
echo host_str=$(grep "HOST='$1'" $VESTA/conf/mysql.conf)
i get empty result , although there is HOST in mysql.conf file which i pasted above in code
so any idea whats wrong with it
UPDATE :: Vesta db connect code block
host_str=$(grep "HOST='$1'" $VESTA/conf/mysql.conf)
eval $host_str
if [ -z $HOST ] || [ -z $USER ] || [ -z $PASSWORD ]; then
echo "Error: mysql config parsing failed"
log_event "$E_PARSING" "$EVENT"
exit $E_PARSING
fi
and i get
Error: mysql config parsing failed
$1 is the first parameter of your script.
So, host_str=$(grep "HOST='$1'" $VESTA/conf/mysql.conf) gets the line containing some variables from your file according to your parameter, and eval $host_str sets these variables in your script.
Therefore, your script needs an argument to know which host to look for in your file, in your case, it's localhost, so run: ./yourscript.sh localhost.
You probably don't want to use $1. Rather try this:
echo host_str=$(grep -o "HOST='[^']*'" $VESTA/conf/mysql.conf)
The [^']* expands to everything that happens to be in between the single quotes. The option -o makes sure you only get the matching string, not the whole line, if that is what you want.

In Unix, how to display welcome message if user has logged in from a particular IP (or host)?

I want to display one message if user XYZ has logged in from any IP (or host).
Check to see if you have environment variables such as SSH_CLIENT and SSH_CONNECTION set. If so, you can access these from scripts (perl, bash, etc...) to dynamically generate a welcome message. Below, is a simple perl script to extract the IP address from env var SSH_CLIENT and output a welcome message.
#!/usr/bin/env perl
use strict; use warnings;
my $ip = (split / /, $ENV{SSH_CLIENT})[0];
if ($ip eq 'xxx.xxx.xxx.xxx') {
print "Hello XXXX\n";
}
else {
print "Hello from unknown IP\n";
}
Then you need to execute this script at login time. You can do this by calling the script from the end of /etc/profile.
Also This can be done using shell script as
REMOTE_IP=`echo $SSH_CONNECTION | cut -f1 -d " "`
if [ $REMOTE_IP == 'XXX.XXX.XXX.X' ] ;
then echo "Hi XXX" ;
else echo "Hi, stranger...";
fi
And then run this script from /etc/profile

Resources