![]()
You read this?
http://forum.mikrotik.com/t/persistent-environment-variables/145326/6
Yes, I read and even wrote some messages there. There we came to the conclusion that it is possible to save the function code in Layer7, but it is not possible to restore it from there as a working code, it is restored as a string type, and so far this problem has not been solved.
A small function for sending an SMS message from the router-SSH-client through the modem of the router-SSH-server:
# $1 - router IP
# $2 - username
# $3 - (usbX/lteY)
# $4 - phonenumber
# $5 - SMS-message
:global SSHsend do={
do {:set $1 [:toip $1]} on-error={:return "Error syntax address IP SSH-Server"}
:if (!any $2) do={:return "Error username"}
:if (!any $3) do={:return "Error SMS interface number or type"}
:if (!any $4) do={:global ADMINPHONE; :set $4 $ADMINPHONE}
:if (!any $5) do={:set $5 "test"}
do {
[/system ssh-exec address=$1 user=$2 command="/tool sms send port=\"$3\" phone-number=\"$4\" message=\"$5\""]
} on-error={:return "Error send message from SSH-server"}
:log warning "SMS $5 to a subscriber $4 via modem $3 router ssh-server IP $1 is sent"; :return "Done"
}
:local sshAns [$SSHsend 192.168.1.2 admin lte2 89107777777 "Hello from router!"]
:if ($sshAns!="Done") do={:log error $sshAns}
with me having to send a “CONTINUE” message every 5 gigabytes, every day (an unlimited amount of times) to get another 5GB of data.
If you need to send messages through a remote router, you can use the SSHsend function:
:global SSHsend
:local address XXX.XXX.XXX.XXX
:local user admin
:local port usb2
:local phoneNumber +XYYYYYYYYYY
[$SSHsend $address $user $port $phoneNumber "CONTINUE"]
Sertik do not lost time, is the usual add-spam-later NameSurname
Sertik do not lost time, is the usual add spam later NameSurname
I don’t understand you, REX, what do you mean ?
You reply to one post user, with the username NameSurname, with nonsense post…
are “bot” for spam.
Add later after some weeks on the signature spam links.
Ok, understand.
Hello, Rex !
I ask for your help.
I’m trying to write a function that would create a function from the text of an SSH client script on an SSH server. Everything seems to be correct and a string is created that is identical to your escaped version of the ip2bin function, but the global variable with the code is not created on the remote SSH server. What’s my mistake? I can’t find it at all…
:global ip2bin do={
:local number [:tonum [:toip $1]]
:local ret ""
:for i from=0 to=31 step=1 do={
:set ret "$(($number >> $i) & 1)$ret"
:if ([:tostr $i]~"^(7|15|23)\$") do={:set ret "$2$ret"}
}
:return $ret
}
this code is in the ip2bin script of the same name.
And this is my function:
:global SSHfunc do={
# $1 - SSH-server address
# $2 - username
# $3 - script name with function text on SSH client
:local ReplaceChars do={:local ret ""
:local char ""
:for i from=0 to=([:len $1] - 1) do={
:set char [:pick $1 $i ($i + 1)]
:if ($char = "\r") do={:set $char "\3B\5C"}
# :if ($char = "\n") do={:set $char ""}
:if ($char = "\$") do={:set $char "\5C\24"}
:if ($char = "\"") do={:set $char "\5C\22"}
:if ($char = "}") do={:set $char " }"}
:set $ret "$ret$char"
}
:if ([:pick $ret ([:len $ret]-1) [:len $ret]]="\5C") do={:set $ret [:pick $ret 0 ([:len $ret]-1)]}
:return $ret
}
:if ([:len $1]=0) do={:return "Error IP SSH-Server"}
do {:set $1 [:toip $1]} on-error={:return "Error syntax address IP SSH-Server"}
:if (!any $2) do={:return "Error username"}
:if ([:len $3]=0) do={:return "Error Script-sourse name not set"}
:if ([:len [/system script find name=$3]]=0) do={:return "Error Script $3 no find in repository"}
:global F
:do {
:set F [/system script get $3 source]
:put $F
} on-error={:return "Error reading a script into a variable script larger than 4096 bytes"}
:set F [$ReplaceChars $F]
:put $F
:do {
[/system ssh-exec address=$1 user=$2 command="$F"]
} on-error={:return "Error transmitting or creating a script on the SSH server"}
:log warning "Script $3 was transferred to the SSH server $1 and set function"; :return "Done"
}
:local sshAns [$SSHfunc 192.168.1.2 admin ip2bin]
:if ($sshAns!="Done") do={:log error $sshAns}
I understand what can be done differently - transfer the source script to the SSH server and execute it - the same function definition will occur. But we are not looking for easy ways - we want to do exactly the first option. Although in the second option, you will also have to change the same characters in the transmitted string.
Too much escape will kill you…
/system script
add dont-require-permissions=no name=ip2bin owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
source=":global ip2bin do={\r\
\n :local number [:tonum [:toip \$1]]\r\
\n :local ret \"\"\r\
\n :for i from=0 to=31 step=1 do={\r\
\n :set ret \"\$((\$number >> \$i) & 1)\$ret\"\r\
\n :if ([:tostr \$i]~\"^(7|15|23)\\\$\") do={:set ret \"\$2\$ret\"}\r\
\n }\r\
\n :return \$ret\r\
\n}"
:global scr2sshcmd do={
:local remote [:toip $1] ; :local usr [:tostr $2]
:local scr [:tostr $3] ; :local ext [:tostr $4]
/system script
:if ([:typeof $remote] = "nil") do={:return "IP wrong or not defined"}
:if ([:len $usr] < 1) do={:return "user not defined"}
:if ([:len [find where name=$scr]] != 1) do={:return "script not found or not defined"}
:if ($ext~"(\a|\b|\f|\n|\r|\t|\v)") do={:return "invalid characters on command extension"}
:local source [get $scr source]
:local cmd ""
:for idx from=0 to=([:len $source] - 1) do={
:local char [:pick $source $idx]
:if ($char~"(\a|\b|\f|\n|\r|\v)") do={:set char ";"}
:if ($char = "\t") do={:set char " "}
:set cmd "$cmd$char"
}
:return [/system ssh-exec address=$remote user=$usr command="$cmd;$ext;:return \"DONE\""]
}
:put [$scr2sshcmd 192.168.1.2 admin ip2bin (“:global test [$ip2bin 127.0.0.1]”)]
I do not implement ssh-exec error management.
Rex, thank you so much! I inserted your symbol replacement function into mine, everything seems to be the same as yours, I can’t understand why it doesn’t work. Sorry for taking up your time.
:global SSHscript do={
:local ReplaceChars do={
:local cmd ""
:for idx from=0 to=([:len $1] - 1) do={
:local char [:pick $1 $idx]
:if ($char = "\a") do={:set char ";"}
:if ($char = "\b") do={:set char ";"}
:if ($char = "\f") do={:set char ";"}
:if ($char = "\t") do={:set char " "}
:if ($char = "\v") do={:set char ";"}
:if ($char = "\n") do={:set char ";"}
:if ($char = "\r") do={:set char ";"}
:set cmd "$cmd$char"
}
:return $cmd}
:if ([:len $1]=0) do={:return "Error IP SSH-Server"}
do {:set $1 [:toip $1]} on-error={:return "Error syntax address IP SSH-Server"}
:if (!any $2) do={:return "Error username"}
:if ([:len $3]=0) do={:return "Error Script-sourse name not set"}
:if ([:len $4]=0) do={:return "Error Script SSH name not set"}
:if ([:len [/system script find name=$3]]=0) do={:return "Error Script $3 no find in repository"}
:global F
:do {
:set F [/system script get $3 source]
:log warning $F
:set F [$ReplaceChars $F]
:log error $F
} on-error={:return "Error reading a script into a variable script larger than 4096 bytes"}
:if ([:len $5]=0) do={
:do {
[/system ssh-exec address=$1 user=$2 command="/system script remove \"$4\""]
:delay 2s;
[/system ssh-exec address=$1 user=$2 command="/system script add name=\"$4\" source=\"$F\""]
} on-error={:return "Error transmitting or creating a script on the SSH server"}
:log warning "Script $3 was transferred to the SSH server $1"; :return "Done"
}
:if (([:len $5]!=0) && ($5="run")) do={
:do {
[/system ssh-exec address=$1 user=$2 command="/system script remove \"$4\""]
:delay 2s;
[/system ssh-exec address=$1 user=$2 command="/system script add name=\"$4\" source=\"$F\"; /system script run \"$4\"; /system script remove \"$4\""]
} on-error={:return "Error transmitting or creating a script on the SSH server"}
:log warning "Script $3 was transferred to the SSH server $1 and executed"; :return "Done"
} else={:return "Error parametr $5"}
}
:local sshAns [$SSHscript 192.168.1.2 admin ip2bin ip2bin]
:if ($sshAns!="Done") do={:log error $sshAns}
:global scr2sshcmd do={
:local remote [:toip $1] ; :local usr [:tostr $2]
:local scr [:tostr $3] ; :local ext [:tostr $4]
/system script
:if ([:typeof $remote] = "nil") do={:return "IP wrong or not defined"}
:if ([:len $usr] < 1) do={:return "user not defined"}
:if ([:len [find where name=$scr]] != 1) do={:return "script not found or not defined"}
:if ($ext~"(\a|\b|\f|\n|\r|\t|\v)") do={:return "invalid characters on command extension"}
:local source [get $scr source]
:local cmd ""
:for idx from=0 to=([:len $source] - 1) do={
:local char [:pick $source $idx]
:if ($char~"(\a|\b|\f|\n|\r|\v)") do={:set char ";"}
:if ($char = "\t") do={:set char " "}
:set cmd "$cmd$char"
}
:return [/system ssh-exec address=$remote user=$usr command="$cmd;$ext;:return \"DONE\""]
}
:put [$scr2sshcmd 192.168.1.2 admin (":global test [\$ip2bin 127.0.0.1]")]
Didn’t get the idea of $4. Where is he ? Do you mean that you can pass function parameters in $4?
I am writing such a library and in logic it is almost ready. What do you think, maybe you already have such developments and I am reinventing the wheel? If you think that the idea is not bad, maybe you will agree to look at my code? For a programmer like you, this is probably an easy task.
Creating the SSH-exec labruary (list of planned features)
When creating scripts and tasks of the Scheduler on a remote MT, create comments to them (if necessary)
\
Is better you start with something that work, instead to try to fix your code…
Is why I rewrite from 0 the function instead to try to fix your.
You can use all the Snippets on my signature links and all the other script on forum,
also this topic is full of usable code.
I promise you nothing, it can’t be like a job.
If you write something it is not sure that I see it and that I correct it,
especially if it’s written hard to read, but you never know.
if you had copied correctly you would not have written on ReplaceChars
:if ($char = "\a") do={:set char ";"}
:if ($char = "\b") do={:set char ";"}
:if ($char = "\f") do={:set char ";"}
:if ($char = "\t") do={:set char " "}
:if ($char = "\v") do={:set char ";"}
:if ($char = "\n") do={:set char ";"}
:if ($char = "\r") do={:set char ";"}
but only
:if ($char~"(\a|\b|\f|\n|\r|\v)") do={:set char ";"}
:if ($char = "\t") do={:set char " "}
after install the function, the 4th parameter add some command(s), like on the example (escaped)
:global test [$ip2bin 127.0.0.1]
it use instantly the transferred (from source) ip2bin function to add one global variable (on remote machine), called test, with inside the binary value of 127.0.0.1
Check again the function and command line example I post on previous post,
You have read a preliminar version not finished than I post for not lost what I done till that moment.
Check also the “example code” of the command line, have the 4th parameter now.
(because in the preliminary version of the example the 3rd value was missing: the name of the script)
Thanks Rex. For me, scripting is not a job, but a hobby. I’m a doctor.
:global scr2sshcmd do={
:local remote [:toip $1] ; :local usr [:tostr $2]
:local scr [:tostr $3] ; :local ext [:tostr $4]
/system script
:if ([:typeof $remote] = "nil") do={:return "IP wrong or not defined"}
:if ([:len $usr] < 1) do={:return "user not defined"}
:if ([:len [find where name=$scr]] != 1) do={:return "script not found or not defined"}
:if ($ext~"(\a|\b|\f|\n|\r|\t|\v)") do={:return "invalid characters on command extension"}
:local source [get $scr source]
:local cmd ""
:for idx from=0 to=([:len $source] - 1) do={
:local char [:pick $source $idx]
:if ($char~"(\a|\b|\f|\n|\r|\v)") do={:set char ";"}
:if ($char = "\t") do={:set char " "}
:set cmd "$cmd$char"
}
:return [/system ssh-exec address=$remote user=$usr command="$cmd;$ext;:return \"DONE\""]
}
:put [$scr2sshcmd 192.168.1.2 admin (":global test [\$ip2bin 127.0.0.1]")]
I’m sorry, again I don’t see $4 in the function call, three parameters are used: address, user and command:
address 192.168.1.2
user admin
command (“:global test [$ip2bin 127.0.0.1]”)
So ? Where is $4?
Should be:
:put [$scr2sshcmd 192.168.1.2 admin Ourscript (":global test [\$ip2bin 127.0.0.1]")]
Is better you read all before posting something...
So I read it, but apparently I didn’t understand because of my bad English