i am not aware of lua script but i need some help.
Basically current lua script will receive structure.
in those structure has address parameter where will get two index parameters(ipv6 & ipv4) addresses.
lua script need to implement below case
ping ipv6 address and result will get store in local variable.
if local variable gets (ping success) will connect/call uv.tcp_connect for passed ipv6 address.
otherwise i will check the same for ipv4 address and try to connect/call uv.tcp_connect.
I am using online lua editor there its returning nil.
local results = load('ping -q -c1 -6 localhost 2>&1 >/dev/null && printf "IPv6: true" || (ping -q -c1 www.google.com 2>&1 >/dev/null && printf "IPv4 true" || printf "false")')
print(results)
output is:nil
and
if i am using in lua online editor ..
local handler = io.popen("ping -c 3 -i 0.5 www.google.com")-- wrong here.
local response = handler:read("*a")
print(response)
output error :
lua: main.lua:3: expected near '"ping -c 3 -i 0.5 www.google.com"'
kindly suggest me , am i missing something above.
To store output of system commands i suggest io.popen().
An example for conditional ping that tries first IPv6 and if fail IPv4...
> code.cmd
-- cmd(shell)
return function(shell)
return io.popen(shell, 'r'):read('a+')
end
> results={}
> results.ping=load(code.cmd)()('ping -q -c1 -6 localhost 2>&1 >/dev/null && printf "IPv6: true" || (ping -q -c1 localhost 2>&1 >/dev/null && printf "IPv4 true" || printf "false")')
> print(results.ping)
IPv6: true
...typed in a Lua console.
EDIT
Online Lua Environments dont support above code!
Related
I am working on a scanner with Nmap. I am expanding this scanner with NSE scripts.
I have a script that runs 'Nuclei', using Nmap. This script is made and used by someone else, and it has worked before. However, when I run it now, I get the error: sh: 1: nuclei: not found.
Nuclei is (of course) installed on the system, and it works as root and normal user. It looks like Nmap doesn't have access to Nuclei, but how to fix?
The NSE script:
local shortport = require "shortport"
local stdnse = require "stdnse"
portrule = function(host,port)
return true
end
action = function(host,port)
local handle = ""
local always = stdnse.get_script_args("nuclei.always")
local hostname = stdnse.get_hostname(host)
if port.number == 80 then
handle = io.popen("nuclei -u http://" .. hostname .. " -nc -silent -etags intrusive -rl 30 -rlm 1000 -bs 8 -c 8")
elseif port.number == 443 then
handle = io.popen("nuclei -u https://" .. hostname .. " -nc -silent -etags intrusive -rl 30 -rlm 1000 -bs 8 -c 8")
elseif always == "yes" then
handle = io.popen("nuclei -u " .. hostname .. " -nc -silent -etags intrusive -rl 30 -rlm 1000 -bs 8 -c 8")
end
local result = handle:read("*a")
handle:close()
return result
end
The Nmap command:
nmap -script=nuclei.nse -p80,443 -T2 IPADDRESS
Nmap is installed using Snap. It runs on Ubuntu.
The solution was quite simple:
Install nmap using apt, instead of snap did the job.
I have 5 containers running one after another. First 3, (ABC) are very minimal. ABC containers need to be health checked, but curl,wget cannot be run on them, so currently I just run test:[CMD-SHELL], "whoami || exit 1" in docker-compose.yml. Which seems to bring them to a healthy state. Other 2 (DE) dependent on ABC to be healthy are being checked using test: [CMD-SHELL] , "curl --fail http://localhost" command. My question is how can I properly check health of those minimal containers, without using curl, wget etc. ?
If you can live with a TCP connection test to your internal service's port, you could use /dev/tcp for this:
HEALTHCHECK CMD bash -c 'echo -n > /dev/tcp/127.0.0.1/<port>'
Like this:
# PASS (webserver is serving on 8099)
root#ab7470ea0c8b:/app# echo -n > /dev/tcp/127.0.0.1/8099
root#ab7470ea0c8b:/app# echo $?
0
# FAIL (webserver is NOT serving on 9000)
root#ab7470ea0c8b:/app# echo -n > /dev/tcp/127.0.0.1/9000
bash: connect: Connection refused
bash: /dev/tcp/127.0.0.1/9000: Connection refused
root#ab7470ea0c8b:/app# echo $?
1
Unfortunately, I think this is the best that can be done without installing curl or wget.
I have a server which is running an apache hive service on port 9083. The thing is it doesn't support http protocol (but uses thrift protocol).so I can't simply add
HEALTHCHECK CMD http://127.0.0.1:9083 || exit 1 # this check fails
All I want is to check if that port is open. I have netstat and curl on server but not nc.
So far I tried the below options, but none of them is suitable as a health check.
netstat -an | grep 9083 | grep LISTEN | echo $? # This works
netstat -an | grep 9084 | grep LISTEN | echo $? # but so does this
The problem as I interpret from the above is it's simply telling me my syntax is correct, but not really testing if that port is really listening
because when I do netstat -an I get the following output,which clearly shows only 9083 is listening but not 9084
Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0
0.0.0.0:9083 0.0.0.0:* LISTEN tcp 0 0
Though answering an old question, for future googlers, the following worked for me:
HEALTHCHECK CMD netstat -an | grep 9083 > /dev/null; if [ 0 != $? ]; then exit 1; fi;
The shorter version of it:
netstat -ltn | grep -c 9083
Used options:
netstat:
-l - display listening server sockets
-t - display TCP sockets only
-n - don't resolve names
grep
-c - returns a number of founded lines, but it also gives a useful exit code; 0 if found, 1 if not found
You can use /dev/tcp
Like this :
printf "GET / HTTP/1.1\n\n" > /dev/tcp/127.0.0.1/9083
For more information, you can check this : http://www.tldp.org/LDP/abs/html/devref1.html#DEVTCP
Piotr Perzynas answer is quite good, but it will also return 0 if thereās a port like 19083 because it finds the substring 9083 in that line.
a better check would be:
netstat -ltn | grep -c ":9083"
I really loved Wassim Dhif answer. Mostly because it does not depend on netstat.
Netstat was obsolete before the question was asked.
From netstat's manpage:
Note
This program is obsolete. Replacement for netstat is ss. Replacement for netstat -r is ip route. Replacement for netstat -i is ip -s link. Replacement for netstat -g is ip maddr.
And you need netstat (or ss) installed in the container. You only want to check if a port is open. Wassim Dhif's answer just needs bash (and yes, not every image has it). In my experience, you usually want the image as light as possible.
In my compose I used it as follows:
healthcheck:
test: "bash -c 'printf \"GET / HTTP/1.1\n\n\" > /dev/tcp/127.0.0.1/8080; exit $?;'"
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
Note that the string test is equivalent to specifying CMD-SHELL followed by that string (from the Compose Specification
I've been using GNU parallel and I want to keep output order (--kepp-order), grouped by jobs (--grouped) but also with sorted stdout and stderr. Right now, the grouped options first print stdout and only after does it print stderr.
As an example, any way that these two commands give the same output?
seq 4 | parallel -j0 'sleep {}; echo -n start{}>&2; sleep {}; echo {}end'
seq 4 | parallel -j0 'sleep {}; echo -n start{} ; sleep {}; echo {}end'
thanks,
As per the comment to the other answer, to keep the output ordered, simply have parallel's bash invocation redirect stderr to stdout:
parallel myfunc '2>&1'
E.g.,
parallel -j8 eval \{1} -w1 \{2} '2>&1' ::: "traceroute -a -f9" traceroute6 ::: ordns.he.net one.one.one.one google-public-dns-a.google.com
You cannot do that if you still want stderr and stdout to be separated.
The reason for this is that stderr and stdout are buffered to 2 different files using buffered output.
But maybe you can explain a bit more on what you need this for. In that case there might be a solution.
Assuming that you don't have to use gnu parallel, and the main requirements are parallel execution with maintained ordered output of both stderr and stdout; we can create a solution that allows for the following example usage(plus providing return code), where you will have the results of the executions in a list, where each list element is in return a list of 3 strings: indexed as 0=stdout, 1=stderr and 2=return code.
source mapfork.sh
ArgsMap=("-Pn" "-p" "{}" "{}")
Args=("80" "google.com" "25" "tutanota.com" "80" "apa bepa")
declare -a Results=$(mapfork nmap "(${ArgsMap[*]#Q})" "(${Args[*]#Q})")
So, in order to print for example the stderr results, of the third destination ("apa bepa"), you can do:
declare -a res3="${Results[2]}"
declare -p res3
# declare -a res3=([0]=$'Starting Nmap 7.70 ( https://nmap.org ) at 2019-06-21 18:55 CEST\nNmap done: 0 IP addresses (0 hosts up) scanned in 0.09 seconds' [1]=$'Failed to resolve "apa bepa".\nWARNING: No targets were specified, so 0 hosts scanned.' [2]="0")
printf '%b\n' "${res3[1]}"
mapfork.sh is shown below. It is a bit complicated but it's parts have been explained in other answers so I won't provide the details here as well:
Capture both stdout and stderr in Bash [duplicate]
How can I make an array of lists (or similar) in bash?
#!/bin/bash
# reference: https://stackoverflow.com/questions/13806626/capture-both-stdout-and-stderr-in-bash
nullWrap(){
local -i i; i="$1"
local myCommand="$2"
local -a myCommandArgs="$3"
local myfifo="$4"
local stderr
local stdout
local stdret
. <(\
{ stderr=$({ stdout=$(eval "$myCommand ${myCommandArgs[*]#Q}"); stdret=$?; } 2>&1 ;\
declare -p stdout >&2 ;\
declare -p stdret >&2) ;\
declare -p stderr;\
} 2>&1)
local -a Arr=("$stdout" "$stderr" "$stdret")
printf "${i}:%s\u0000" "(${Arr[*]#Q})" > "$myfifo"
}
mapfork(){
local command
command="$1"
local -a CommandArgs="$2"
local -a Args="$3"
local -a PipedArr
local -i i
local myfifo=$(mktemp /tmp/temp.XXXXXXXX)
rm "$myfifo"
mkfifo "$myfifo"
local -a placeHolders=()
for ((i=0;i<${#CommandArgs[#]};i++)); do
[[ "${CommandArgs[$i]}" =~ ^\{\}$ ]] && placeHolders+=("$i") ;done
for ((i=0;i<${#Args[#]};i+=0)); do
# if we have placeholders in CommandArgs we need to take args
# from Args to replace.
if [[ ${#placeHolders[#]} -gt 0 ]]; then
for ii in "${placeHolders[#]}"; do
CommandArgs["$ii"]="${Args[$i]}"
i+=1; done; fi
nullWrap "$i" "$command" "(${CommandArgs[*]#Q})" "$myfifo" &
done
for ((i=0;i<${#Args[#]};i+=$(("${#placeHolders[#]}")))) ; do
local res
res=$(read -d $'\u0000' -r temp <"$myfifo" && printf '%b' "$temp")
local -i resI
resI="${res%%:*}"
PipedArr[$resI]="${res#*:}"
done
# reference: https://stackoverflow.com/questions/41966140/how-can-i-make-an-array-of-lists-or-similar-in-bash
printf '%s' "(${PipedArr[*]#Q})"
}
I am attempting to use popen to pipe a string containing multiple quotes to netcat. I have a Python command that works fine but I am turning it into an nmap script. I am not as familiar with Lua.
Python version:
python -c 'print "\x1b%-12345X#PJL FSDIRLIST NAME=\"0:\\..\\..\\..\\\" ENTRY=1 COUNT=999999\x0d\x0a\x1b%-12345X\x0d\x0a"' | nc 192.168.0.1 9100
Lua attempted version:
local handle = assert(io.popen("python -c 'print \"\x1b%-12345X#PJL FSDIRLIST NAME=\"0:\\..\\..\\..\\\" ENTRY=1 COUNT=999999\x0d\x0a\x1b%-12345X\x0d\x0a\"' | nc " .. host .. " " .. port, "r"))
This results in the following error:
File "<string>", line 1
print "2345X#PJL FSDIRLIST NAME="0:\..\..\..\" ENTRY=1 COUNT=999999
Is there a way to organize that string so that Lua will accept it?
Try using a long string
[[python -c 'print "\x1b%-12345X#PJL FSDIRLIST NAME=\"0:\\..\\..\\..\\\" ENTRY=1 COUNT=999999\x0d\x0a\x1b%-12345X\x0d\x0a"' | nc 192.168.0.1 9100]]