查询Erlang进程的状态?

查询Erlang进程的状态?,erlang,Erlang,Erlang中的一种常见模式是维护状态的递归循环: loop(State) -> receive Msg -> NewState = whatever(Msg), loop(NewState) end. Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false] Eshell V5.6.5 (abort with

Erlang中的一种常见模式是维护状态的递归循环:

loop(State) ->
  receive
    Msg ->
      NewState = whatever(Msg),
      loop(NewState)
  end.
Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
有没有办法用bif或跟踪之类的工具来查询正在运行的进程的状态?由于崩溃消息会显示“…当状态为…”并显示崩溃进程的状态,我认为这很容易,但我很失望,因为我没有找到一个bif来执行此操作

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
因此,我认为使用dbg模块的跟踪可以做到这一点。不幸的是,我相信因为这些循环是尾部调用优化的,dbg将只捕获对函数的第一个调用

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           

有什么解决办法吗?

看起来你在无中生有地解决问题。erlang:process_info/1提供了足够的调试信息。如果您确实需要循环函数参数,为什么不将其返回给调用者,以响应您自己定义的一条特殊消息

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
更新: 只是为了澄清术语。在语言级别上最接近“进程状态”的是进程字典,它的使用是非常不鼓励的。可以通过erlang:process\u info/1或erlang:process/2查询。 您实际需要的是跟踪进程的本地函数调用及其参数:

-module(ping).
-export([start/0, send/1, loop/1]).                                                          

start() ->                                                                                   
     spawn(?MODULE, loop, [0]).                                                              

send(Pid) ->                                                                                 
    Pid ! {self(), ping},                                                                    
    receive                                                                                  
    pong ->                                                                                  
         pong                                                                                
    end.                                                                                     

loop(S) ->                                                                                   
    receive                                                                                  
    {Pid, ping} ->                                                                           
        Pid ! pong,                                                                          
        loop(S + 1)                                                                          
    end.                                                                                    
Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
控制台:

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
Erlang(BEAM)emulator 5.6.5版[源代码][smp:2][异步线程:0][内核轮询:false]
Eshell V5.6.5(使用^G中止)
1> l(平)。
{模块,ping}
2> erlang:trace(all,true,[call])。
23
3> erlang:trace_模式({ping,''.','.'},true,[local])。
5.
4> Pid=ping:start()。
5> ping:发送(Pid)。
庞
6> 刷新()。
Shell获取了{trace,,call,{ping,loop,[0]}
Shell获取了{trace,,call,{ping,loop,[1]}
好啊
7>                                                                                           

据我所知,您无法将参数传递给本地调用的函数。我希望有人能证明我错了

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
-module(loop).
-export([start/0, loop/1]).
start() ->
  spawn_link(fun () -> loop([]) end).
loop(State) ->
  receive 
    Msg ->
      loop([Msg|State])
  end.
如果要跟踪此模块,请在shell中执行以下操作

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
dbg:tracer().
dbg:p(new,[c]).                   
dbg:tpl(loop, []).
sys:get_status(list_to_pid("<0.1012.0>")).
使用此跟踪设置,您可以看到本地调用(tpl中的“l”表示也将跟踪本地调用,而不仅仅是全局调用)

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
5>Pid=loop:start()。
()调用循环:'-start/0-fun-0-'/0
()调用循环:循环/1
6> Pid!福。
()调用循环:循环/1
福
如您所见,只包括电话。看不到任何争论

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
我的建议是将调试和测试的正确性建立在发送的消息上,而不是进程中保存的状态上。也就是说,如果您向流程发送了一组消息,请断言它做了正确的事情,而不是它有一组特定的值

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           

当然,您也可以在代码中临时添加一些
erlang:display(State)
调用。可怜的人的调试。

如果您的进程正在使用OTP,这就足够了

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
您提到的错误消息由SASL显示。SASL是OTP中的错误报告守护进程

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
示例代码中引用的状态只是尾部递归函数的一个参数。除了跟踪BIF之外,没有任何方法可以提取它。我想这在生产代码中不是一个合适的解决方案,因为跟踪仅用于调试目的

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
适当的、经过行业测试的解决方案是在您的项目中广泛使用OTP。然后,您可以充分利用SASL错误报告,
rb
模块收集这些报告,
sys
-检查正在运行的OTP兼容进程的状态,
proc_lib
-使短期进程符合OTP,等等

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
{status,Pid,_,[_,_,_,_,[_,_,{data,[{_,State}]}]]} = sys:get_status(Pid).
这就是我用来获取gen_服务器状态的方法。(试图将其作为注释添加到上面的回复中,但无法正确设置格式。)

这是一个可以在shell中使用的“oneliner”

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           
dbg:tracer().
dbg:p(new,[c]).                   
dbg:tpl(loop, []).
sys:get_status(list_to_pid("<0.1012.0>")).
sys:get_status(list_to_pid(“”))。

它可以帮助您将pid字符串转换为pid。

如果您使用OTP,那么有一个比所有这些更好的答案:

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           

Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>                                                                                           

可能当时还不存在。

因为erlang有所有这些很酷的设备来检查和调试实时系统,所以我希望有一些通用的东西。你不认为知道进程的状态对调试有用吗?为什么任何语言中的调试器都有很多用于检查和与变量状态交互的功能?太棒了。这就是我一直在寻找的。我想让我的孩子同时使用的http请求(使用ibrowse)的数量保持在100以下。在本例中,我有一个使用计数器的节流过程。我担心计数器将与正在计数的资源不同步,应用程序将越来越慢。所以,问题是我不能轻易地测试它是否做了正确的事情。程序将继续正常运行,只是速度会慢一些
Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]  

Eshell V5.6.5  (abort with ^G)                                                               
1> l(ping).                                                                                  
{module,ping}                                                                                
2> erlang:trace(all, true, [call]).                                                          
23                                                                                           
3> erlang:trace_pattern({ping, '_', '_'}, true, [local]).                                    
5                                                                                            
4> Pid = ping:start().                                                                       
<0.36.0>                                                                                     
5> ping:send(Pid).                                                                           
pong                                                                                         
6> flush().                                                                                  
Shell got {trace,<0.36.0>,call,{ping,loop,[0]}}                                              
Shell got {trace,<0.36.0>,call,{ping,loop,[1]}}                                              
ok                                                                                           
7>