How to get the output of execute shell script in lua api - bash

I am newbie in luci and lua api. Now I have problem about remove firewall rule from luci webgui in opnewrt. I know delete the rule is using the uci command : uci delete firewall.#rule[index]
But I don't know the index exectly. So I use blow shell script name index.sh to find the index by key word.
uci show firewall | grep $1 | grep -oE '\[.*?\]' | sed 's/[][]//g' | head -n 1
Here $1 is the mac address.
My process is get the mac address from luci web and remove the firewall rule of block the
network access from the mac address I set before. To recover the network access of the mac address.
But I use the lua api of luci.sys.exec and luci.util.exec to get the output of firewall rule index that are all wrong.
My example code:
1.Get the mac address from luci
local del_mac = protocol.urldecode(luci.http.formvalue("deleteMac"))
2.Execute the the shell script to get the index
local ruleindex = ut.trim(tostring(luci.sys.exec("index.sh '" .. del_mac .."'"))
local uci_delete_rule = "uci delete firewall.#rule['" .. ruleindex .. "]'"
luci.sys.exec(uci_delete_rule)
or
local index = "index.sh %s" %{list_del_mac}
local rule_index = ut.trim(tostring(luci.util.exe(index)))
local uci_delete_rule = "uci delete firewall.#rule['" .. rule_index .. "]'"
luci.sys.exec(uci_delete_rule)
3.Reload the firewall rule
luci.sys.exec("uci commit firewall")
luci.sys.exec("fw3 reload")
Can anyone help me to reslove the problem?
Thank you for your help

This doesn't look right to me: "index.sh %s" %{list_del_mac} Unless it's short for string.format in luci, that's not proper Lua. Concatenate your command string, or actually use string.format
"index.sh " ..list_del_mac
or
string.format( "index.sh %s", list_del_mac )
also, to get the return value after execution, you need to send it to a variable
return_value = luci.sys.exec(uci_delete_rule)
print( return_value )

Related

question about Mikrotik ARP list of IP Filtering terminal command

I have this script for mikrotik terminal command
":local arp [:toarray [/ip arp print as-value where dynamic && interface"bridge3" && address in "192.168.4.0/24" ]];"
this script is working for 1 subnet. but I have many IPs that i want to include on this line of script eg. 192.168.5.0/24, 192.168.6.0/24, 192.168.7.0/24, 192.168.8.0/24, 192.168.9.0/24, 192.168.10.0/24 I want to include those ip on this script. example:
":local arp [:toarray [/ip arp print as-value where dynamic && interface"bridge3" && address in "192.168.4.0/24,192.168.5.0/24,192.168.6.0/24,192.168.7.0/24, 192.168.8.0/24,192.168.9.0/24,192.168.10.0/24" ]];"
but not working. if I use "192.168.0.0/20" its working, the problem is I dont want to include 192.168.1.0/24, 192.168.2.0/24, 192.168.3.0/24.
what is the correct terminal command to include those ips from 192.168.4.0 up to 192.168.10.255?
thanks in advance!!
First, you can print all addresses which are in subnet1 OR in subnet2, etc.:
/ip arp print as-value where dynamic && \
interface=bridge3 && (address in "192.168.4.0/24" || address in "192.168.5.0/24" \
|| address in "192.168.6.0/24")
Second, depending on your needs, you may want to combine multiple contiguous /24 subnets to a bigger one. E.g., 192.168.4.0/24 + 192.168.5.0/24 + 192.168.6.0/24 + 192.168.7.0/24 = 192.168.4.0/22 - that can be used to simplify your list(s).

Ssh not working when host is taken using grep

When I'm hardcoding i. e.
server1=ip-10.237.40.10-aws-n-myhost
ssh - i /home/<passwordfile> akhil#$server1
It is working,but when I'm greping the host from other file its not working
Eg:
server2=$(grep - e host /home/akhil/configuration. File | awk FS, '{print $2} ' )
echo $server2
ssh - i /home/<passwordfile> akhil#$server2
While printing server 2 is fine, but when it is used in ssh I'm getting a error saying : not known host name.
I want to automate the script with a configuration file so that when ever the cluster changes I could simply change the ip address in configfile instead of changing in all my scripts.
I need help in this.
Thanks

Loop for checking string change in system function output (monitoring a DNS update)

I am switching DNS servers and I'd like to write a short ruby script that runs every 10s and triggers a local Mac OS X system notification as soon as my website resolves to a different IP.
Using terminal-notifier sending a system notification is as easy as this
terminal-notifier -message "DNS Changed"
I'd like to trigger it as soon as the output of
ping -i 10 mywebsite.com
... changes or simply does not contain a defined IP string anymore.
> 64 bytes from 12.34.56.789: icmp_seq=33 ttl=41 time=241.564 ms
in this case "12.34.56.789".
How do I monitor the change of the output string of the ping -i 10 mywebsite.com and call the notification function once a change has been detected?
I thought this might be a nice practice while waiting for the DNS to be updated.
Try this:
IP = "12.34.56.789"
p = IO.popen("ping -i 10 mywebsite.com")
p.each_line do |l|
if(! l =~ /from #{IP}/) #The IP has changed
system("terminal-notifier -message \"DNS Changed\"")
end
end

Setting proxy on .Rprofile on OSX fails

In order to access CRAN packages from within R on OSX I've been using
Sys.setenv(http_proxy="http://blah_blah:1234/")
as the first command in the R GUI for a while, but would really like to set this proxy automatically.
I've tried unsuccessfully to get the same command to work in a .Rprofile file in ~/
I've also tried http_proxy="http://blah_blah:1234/", but this fails too.
The error I get when I try to view packages is a drop-down window that says:
Fetching Package List Failed
Please consult R Console output for details
The GUI then gives:
Error in read.dcf(file = tmpf) : Line starting '<head> ...' is malformed!
The .Rprofile file itself seems to be loading (checked using cat("my profile works\n"))
Couldn't you just use .First ?
http://cran.r-project.org/doc/manuals/R-intro.html#Customizing-the-environment
This thread appears first when searching for setting R proxy on OS X, so here's what I use in my .Rprofile:
Sys.setenv(http_proxy=system("networksetup -getwebproxy Ethernet | awk {'print $2'} | awk {'getline l2; getline l3; print \"http://\"l2\":\"l3'} | head -n 1",intern=TRUE))
Change Ethernet to Airport if necessary.
Credit for the awk part goes to Chealion
I think I have managed to solve this using trial and error...
A combination of .First and Sys.setenv() works.
If anyone has any ideas I'd be interested to know why.

Getting the Hostname or IP in Ruby on Rails

I'm in the process of maintaining a Ruby on Rails app and am looking for an easy way to find the hostname or IP address of the box I'm on (since it's a VM and new instances may have different hostnames or IP addresses). Is there a quick and easy way to do this in Ruby on Rails?
Edit: The answer below is correct but the clarification Craig provided is useful (see also provided link in answer):
The [below] code does NOT make a
connection or send any packets (to
64.233.187.99 which is google). Since UDP is a stateless protocol connect()
merely makes a system call which
figures out how to route the packets
based on the address and what
interface (and therefore IP address)
it should bind to. addr() returns an
array containing the family (AF_INET),
local port, and local address (which
is what we want) of the socket.
Hostname
A simple way to just get the hostname in Ruby is:
require 'socket'
hostname = Socket.gethostname
The catch is that this relies on the host knowing its own name because it uses either the gethostname or uname system call, so it will not work for the original problem.
Functionally this is identical to the hostname answer, without invoking an external program. The hostname may or may not be fully qualified, depending on the machine's configuration.
IP Address
Since ruby 1.9, you can also use the Socket library to get a list of local addresses. ip_address_list returns an array of AddrInfo objects. How you choose from it will depend on what you want to do and how many interfaces you have, but here's an example which simply selects the first non-loopback IPV4 IP address as a string:
require 'socket'
ip_address = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }.ip_address
From coderrr.wordpress.com:
require 'socket'
def local_ip
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
UDPSocket.open do |s|
s.connect '64.233.187.99', 1
s.addr.last
end
ensure
Socket.do_not_reverse_lookup = orig
end
# irb:0> local_ip
# => "192.168.0.127"
Try this:
host = `hostname`.strip # Get the hostname from the shell and removing trailing \n
puts host # Output the hostname
A server typically has more than one interface, at least one private and one public.
Since all the answers here deal with this simple scenario, a cleaner way is to ask Socket for the current ip_address_list() as in:
require 'socket'
def my_first_private_ipv4
Socket.ip_address_list.detect{|intf| intf.ipv4_private?}
end
def my_first_public_ipv4
Socket.ip_address_list.detect{|intf| intf.ipv4? and !intf.ipv4_loopback? and !intf.ipv4_multicast? and !intf.ipv4_private?}
end
Both return an Addrinfo object, so if you need a string you can use the ip_address() method, as in:
ip= my_first_public_ipv4.ip_address unless my_first_public_ipv4.nil?
You can easily work out the more suitable solution to your case changing the Addrinfo methods used to filter the required interface address.
Simplest is host_with_port in controller.rb
host_port= request.host_with_port
This IP address used here is Google's, but you can use any accessible IP.
require "socket"
local_ip = UDPSocket.open {|s| s.connect("64.233.187.99", 1); s.addr.last}
Similar to the answer using hostname, using the external uname command on UNIX/LINUX:
hostname = `uname -n`.chomp.sub(/\..*/,'') # stripping off "\n" and the network name if present
for the IP addresses in use (your machine could have multiple network interfaces),
you could use something like this:
# on a Mac:
ip_addresses = `ifconfig | grep 'inet ' | grep -v 127.0.0.1 | cut -d' ' -f 2`.split
=> ['10.2.21.122','10.8.122.12']
# on Linux:
ip_addresses = `ifconfig -a | grep 'inet ' | grep -v 127.0.0.1 | cut -d':' -f 2 | cut -d' ' -f 1`.split
=> ['10.2.21.122','10.8.122.12']
The accepted answer works but you have to create a socket for every request and it does not work if the server is on a local network and/or not connected to the internet. The below, I believe will always work since it is parsing the request header.
request.env["SERVER_ADDR"]
Put the highlighted part in backticks:
`dig #{request.host} +short`.strip # dig gives a newline at the end
Or just request.host if you don't care whether it's an IP or not.
You will likely find yourself having multiple IP addresses on each machine (127.0.0.1, 192.168.0.1, etc). If you are using *NIX as your OS, I'd suggest using hostname, and then running a DNS look up on that. You should be able to use /etc/hosts to define the local hostname to resolve to the IP address for that machine. There is similar functionality on Windows, but I haven't used it since Windows 95 was the bleeding edge.
The other option would be to hit a lookup service like WhatIsMyIp.com. These guys will kick back your real-world IP address to you. This is also something that you can easily setup with a Perl script on a local server if you prefer. I believe 3 lines or so of code to output the remote IP from %ENV should cover you.
io = IO.popen('hostname')
hostname = io.readlines
io = IO.popen('ifconfig')
ifconfig = io.readlines
ip = ifconfig[11].scan(/\ \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\ /)
The couple of answers with require 'socket' look good. The ones with request.blah_blah_blah
assume that you are using Rails.
IO should be available all the time. The only problem with this script would be that if ifconfig is output in a different manor on your systems, then you would get different results for the IP. The hostname look up should be solid as Sears.
try: Request.remote_ip
remote_ip()
Determine originating IP address. REMOTE_ADDR is the standard but will
fail if the user is behind a proxy. HTTP_CLIENT_IP and/or
HTTP_X_FORWARDED_FOR are set by proxies so check for these if
REMOTE_ADDR is a proxy. HTTP_X_FORWARDED_FOR may be a comma- delimited
list in the case of multiple chained proxies; the last address which
is not trusted is the originating IP.
Update:
Oops, sorry I misread the documentation.

Resources