No output or error message from Erlang shell - erlang

Sometimes when i try to run a command in the Erlang shell (for example calling a function from a module etc) the shell doesn't give any output or error message and just returns. I am sure that i give the command in the right shape (with a dot at the end etc).
To solve this i have to give the following commands in the shell:
'. or ".
And then the shell prints a long atom or what ever and then after that i can run my original command correctly.
Does anyone have seen a same issue? And what is the reason for this?

This looks like there were an initial ' or " in the command line. So the shell is waiting for the second ' or " which closes the atom or string declaration. It prints the evaluation result and is now ready for the next command.
Look at this example in the console (started with erl):
Eshell V10.6.2 (abort with ^G)
1> io:format("Hello world!").
Hello world!ok
2> io:format("Hello world! ).
2> ".
* 2: syntax error before: '.'

Related

io.popen how to get the go output in lua

How could I capture compiler errors go in lua?
I'm trying to get the output of the comp compiler errors in a tmux panel using lua
when executing the script the result is only shown in the current panel and not in the second panel
and the /tmp/output file is always empty
cmd=io.popen("go build -gcflags=-e scree.go")
f=io.open("/tmp/output")
f:write(cmd:read("*all"))
for line in f:lines() do
os.execute("tmux run-shell -t 2 'echo " .. line .. "' ")
end
f:close()
Is there any way to do this without using a temporary file?
I'm not totally clear on this. But maybe something like the following. i.e. pipe stderr to stdout and capture the result (not tested).
f = assert (io.popen ("go build -gcflags=-e scree.go 2>&1"))
for line in f:lines() do
os.execute("tmux run-shell -t 2 'echo " .. line .. "' ")
end
f:close()
I think the key is that popen won't capture stderr. See further details about that here

How can I exit a multi-line command sequence in the Erlang shell?

Sometimes in the Erlang shell, if I mistype a command and hit Enter, the shell goes to the next line in anticipation that the command will continue (so the line number on the left stays the same).
For example, I just now mistakenly (on purpose) typed 1> $"X". instead of 1> $X.. After hitting Enter, now the command line is stuck on 1>. I have tried typing . followed by Enter and simply Enter in the hopes of terminating the command sequence, but it doesn't work. Although I have tried, it is very hard to look this up on google because the incredibly common keywords lead to other results.
Is there a way I can break that sequence without having to exit the shell entirely with Ctrl C? The trouble with restarting the shell is all the variables are lost.
you can hit Ctrl-g, which gets you to the "User switch command" this erlang's shell break mode
The prompt will change from > to --->.
In this mode
Type i to interrupt your erlang session
then type c to reconnect to it
erlang shell will then state exception exit: killed and return to the state it was in immediately before you got stuck.
~ → erl
Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
local recon loaded
local stdlib2 loaded
Eshell V8.2 (abort with ^G)
1> $"X".
1> l
1> .
1> .
1>
User switch command
--> i
--> c
** exception exit: killed
1> R=22.
22
2> $"X".
2>
User switch command
--> i
--> c
** exception exit: killed
2> b().
R = 22
ok
3>
I don't know an universal way, and I am interested to know one. On my side I try to figure out what the shell is expecting, in your example, the shell "thinks" that you are typing a string:
The first $" is interpreted as the character '"', so the next '"' is interpreted as the beginning of a string and the shell is waiting for the end of the string before it starts to interpret the next dot as the end of expression.
Type ". and you will get a new prompt.
Edit
When an error is detected by the shell directly, before evaluating the expression, the prompt number doesn't change because there is no result to store:
1> $"X".
1> ".
* 1: syntax error before: X
1> lists:seq(1,5).
[1,2,3,4,5]
2>
If the error is detected during the evaluation of the input, the prompt number is incremented. from the shell point of view there is no difference between a successful evaluation and a faulty one, in both cases the evaluation returns a result:
2> lists:seq("1","5").
** exception error: no function clause matching lists:seq("1","5") (lists.erl, line 243)
3>
The results of each evaluation is stored by the shell, and it can be retrieved using v(N):
3> v(1).
[1,2,3,4,5]
4> v(2).
{'EXIT',{function_clause,[{lists,seq,
["1","5"],
[{file,"lists.erl"},{line,243}]},
{erl_eval,do_apply,6,
[{file,"erl_eval.erl"},{line,674}]},
{shell,exprs,7,[{file,"shell.erl"},{line,686}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,641}]},
{shell,eval_loop,3,
[{file,"shell.erl"},{line,626}]}]}}
5>

Erlang how to start an external script in linux

I want to run an external script and get the PID of the process (once it starts) from my erlang program. Later, I will want to send TERM signal to that PID from erlang code. How do I do it?
I tried this
P = os:cmd("myscript &"),
io:format("Pid = ~s ~n",[P]).
It starts the script in background as expected, but I dont get the PID.
Update
I made the below script (loop.pl) for testing:
while(1){
sleep 1;
}
Then tried to spawn the script using open_port. The script runs OK. But, erlang:port_info/2 troughs exception:
2> Port = open_port({spawn, "perl loop.pl"}, []).
#Port<0.504>
3> {os_pid, OsPid} = erlang:port_info(Port, os_pid).
** exception error: bad argument
in function erlang:port_info/2
called as erlang:port_info(#Port<0.504>,os_pid)
I checked the script is running:
$ ps -ef | grep loop.pl
root 10357 10130 0 17:35 ? 00:00:00 perl loop.pl
You can open a port using spawn or spawn_executable, and then use erlang:port_info/2 to get its OS process ID:
1> Port = open_port({spawn, "myscript"}, PortOptions).
#Port<0.530>
2> {os_pid, OsPid} = erlang:port_info(Port, os_pid).
{os_pid,91270}
3> os:cmd("kill " ++ integer_to_list(OsPid)).
[]
Set PortOptions as appropriate for your use case.
As the last line above shows, you can use os:cmd/1 to kill the process if you wish.

error while executing lua script for redis server

I was following this simple tutorial to try out a simple lua script
http://www.redisgreen.net/blog/2013/03/18/intro-to-lua-for-redis-programmers/
I created a simple hello.lua file with these lines
local msg = "Hello, world!"
return msg
And i tried running simple command
EVAL "$(cat /Users/rsingh/Downloads/hello.lua)" 0
And i am getting this error
(error) ERR Error compiling script (new function): user_script:1: unexpected symbol near '$'
I can't find what is wrong here and i haven't been able to find someone who has come across this.
Any help would be deeply appreciated.
Your problem comes from the fact you are executing this command from an interactive Redis session:
$ redis-cli
127.0.0.1:6379> EVAL "$(cat /path/to/hello.lua)" 0
(error) ERR Error compiling script (new function): user_script:1: unexpected symbol near '$'
Within such a session you cannot use common command-line tools like cat et al. (here cat is used as a convenient way to get the content of your script in-place). In other words: you send "$(cat /path/to/hello.lua)" as a plain string to Redis, which is not Lua code (of course), and Redis complains.
To execute this sample you must stay in the shell:
$ redis-cli EVAL "$(cat /path/to/hello.lua)" 0
"Hello, world!"
If you are coming from windows and trying to run a lua script you should use this format:
redis-cli --eval script.lua
Run this from the folder where your script is located and it will load a multi line file and execute it.
On the off chance that anyone's come to this from Windows instead, I found I had to do a lot of juggling to achieve the same effect. I had to do this:
echo “local msg = 'Hello, world!'; return msg” > hello.lua
for /F "delims=" %i in ('type hello.lua') do #set cmd=%i
redis-cli eval "%cmd%" 0
.. if you want it saved as a file, although you'll have to have all the content on one line. If you don’t just roll the content into a set command
set cmd=“local msg = 'Hello, world!'; return msg”
redis-cli eval "%cmd%" 0

Erlang command line

I need to pass two arguments to my Erlang code. it is working fine in the Erlang shell.
2> crop:fall_velocity(x,23).
21.23205124334434
but how should i run the Erlang code without the Erlang shell. like normal python,c programs.
./program_name (not passing $1 $2 arguments).
I was trying this
erl -noshell -s crop fall_velocity(x,20) -s init stop
But it is giving unexpected token error.
As documentation states, the -s passes all parameters supplied as just one list of atoms and -run does the same but as a list of strings. If you want to call arbitrary function with arbitrary parameter count and types you should use -eval:
$ erl -noshell -eval 'io:format("test\n",[]),init:stop()'
test
$
You can use escript to run Erlang scripts from the command line. In that script you should create a main function which takes an array of arguments as a string.
#!/usr/bin/env escript
main(Args) ->
io:format("Printing arguments:~n"),
lists:foreach(fun(Arg) -> io:format("Got argument: ~p~n", [Arg]) end,Args).
Output:
./escripter.erl hi what is your name 5 6 7 9
Printing arguments:
Got argument: "hi"
Got argument: "what"
Got argument: "is"
Got argument: "your"
Got argument: "name"
Got argument: "5"
Got argument: "6"
Got argument: "7"
Got argument: "9"

Resources