在window中调试的时候我们可以通过启动多个cmd窗口运行Erlang节点,在生产环境中我们需要Erlang服务在Centos服务器上后台运行;这就需要在启动的时候添加启动参数detached来脱离终端:

     -detached Starts the Erlang runtime system detached from the system console. Useful for running daemons and backgrounds processes. Implies -noinput.

对于我们自己的服务,即使部署到了生产环境一定要做到"像魔术师的飞刀,出手但并没有脱手",还是需要一些方式进入到Erlang后台进程来做一些工作比如:查看某一个Erlang节点的运行时信息(内存,进程数等),让服务优雅的退出而不是kill进程,或者做一下热更新(参见:[Erlang 0010] Erlang 热更新 当然热更新可以使用reloader.erl的方案来简化);一开始的时候服务器比较少,我们采用的是JCL的方式去处理的;

Erlang Shell JCL

JCL是Erlang Shell的一种运行模式,即Job Control Mode (JCL, in which jobs can be started, killed, detached and connected).我们启动两个节点来完成这个操作;

2012-11-14新增备注:下面的实验是在Linux下完成的,Windows下JCL需要启动werl.exe

Node_1 添加了-detached选项,启动之后直接在后台运行并没有启动Shell
erl -setcookie abc -name node_1@192.168.1.123 -detached 
Node_2 使用了和Node_1相同的cookie,启动之后进入Erlang Shell界面
erl -setcookie abc -name node_2@192.168.1.123
下面我们开始在node_2@192.168.1.123演练JCL:

Eshell V5.9  (abort with ^G)
(node_2@192.168.1.123)1> node(). %当前这是在node_2
'node_2@192.168.1.123'
(node_2@192.168.1.123)2> %Ctrl + G 进入JCL模式
User switch command
--> h
c [nn] - connect to job
i [nn] - interrupt job
k [nn] - kill job
j - list all jobs
s [shell] - start local shell
r [node [shell]] - start remote shell
q - quit erlang
? | h - this message
--> r'node_1@192.168.1.123' %尝试连接到node_1@192.168.1.123
--> j
1 {shell,start,[init]} %列出所有的Job
2* {'node_1@192.168.1.123',shell,start,[]}
--> c 2 %这里2是job的编号,切换到job 2
Eshell V5.9 (abort with ^G)
(node_1@192.168.1.123)1> node(). %注意提示符,现在已经是在node_1
'node_1@192.168.1.123'
(node_1@192.168.1.123)2> erlang:now().
{1326,801888,347570}
(node_1@192.168.1.123)3> %再一次Ctrl + G
User switch command
--> j
1 {shell,start,[init]}
2* {'node_1@192.168.1.123',shell,start,[]}
--> c 1 %切换到job 1
(node_2@192.168.1.123)2> node(). %注意提示符,我们已经回到了node_2
'node_2@192.168.1.123'
(node_2@192.168.1.123)3>

这样来来回回切换是不是有点盗梦空间的意思?是不是可以更简单一点,比如直接进入node_1呢?借助-remsh参数就可以做到

看看-remsh的说明恰好是我们需要的:

If you want an Erlang node to have a remote job active from the start (rather than the default local job), you start Erlang with the -remsh flag. Example: erl -sname this_node -remsh other_node@other_host

动手试一下:
erl -setcookie abc -name node_3@192.168.1.123 -remsh node_1@192.168.1.123 %%这样就直接进入了node_1节点
注意:直接进入到了node_1,执行完操作了想要退出怎么办? 你要是在这里执行一下q(). node_1这个节点就直接死掉了;
正确的方法还是Ctrl+G进入JCL模式然后执行q命令退出;使用ps aux|grep node查看一下进程是不是还在

ejabberd网站上提到了这个方法 
[1] Attach an Erlang Shell to an Already Running ejabberd Process http://www.ejabberd.im/tricks
[2] Interconnecting Erlang Nodes http://www.ejabberd.im/interconnect-erl-nodes

另一种实用的接入erlang控制台的方法

地址:http://mryufeng.iteye.com/blog/362394  Powered by mryufeng

按照mryufeng老大的方法操练了一番,成功,中间 /usr/local/lib/erlang/bin/start 启动失败,同样是目录和配置文件缺失的问题
mkdir /usr/local/lib/erlang/log
echo "[]." > /usr/local/lib/erlang/releases/R15B/sys.config

Stackoverflow的相关问题: How to create deamon program with erlang? http://stackoverflow.com/questions/5972811/how-to-create-deamon-program-with-erlang

题外话:在embedded模式下是没有交互式shell可用的,能够接入Erlang VM的方法就是to_erl

原理见下图:

erl_call

  随着服务器增多,登录一台台服务器然后使用JCL去做热更新之类的就有点麻烦了,取而代之的解决方案就是ssh登录到每台服务器然后向该服务器上的Erlang节点发送消息,执行热更新(当然不限于热更新了);
  这里有一个很强大的工具可以用:erl_call;erl_call模块的设计目标就是使用Unix Shell脚本与分布式Erlang节点进行交互,erl_call可以启动或者连接到一个分布式的Erlang节点进行简单的方法调用甚至执行表达式序列;erl_call构建在erl_interface之上,通过标准的RPC调用方式与Erlang的rex server交互,并不需要额外的工具支持.注意Erlang节点的RPC服务启动的时候注册的名字是rex http://www.google.com/codesearch#dNzC48WMK6w/lib/kernel/src/rpc.erl&q=rpc%20lang:erlang&type=cs 
看一下erl_call的帮助,注意Erlang版本不同erl_call的路径也有所不同:

Usage: /usr/local/lib/erlang/lib/erl_interface-3.7.6/bin/erl_call [-[demqrsv]] [-c Cookie] [-h HiddenName]
            [-x ErlScript] [-a [Mod [Fun [Args]]]]
            (-n Node | -sname Node | -name Node)

where: -a  apply(Mod,Fun,Args) (e.g -a 'erlang length [[a,b,c]]'
         -c  cookie string; by default read from ~/.erlang.cookie
         -d  direct Erlang output to ~/.erl_call.out.<Nodename>
         -e  evaluate contents of standard input (e.g echo "X=1,Y=2,{X,Y}."|erl_call -e ...)
         -h  specify a name for the erl_call client node
         -m  read and compile Erlang module from stdin
         -n  name of Erlang node, same as -name
         -name  name of Erlang node, expanded to a fully qualified
         -sname name of Erlang node, short form will be used
         -q  halt the Erlang node (overrides the -s switch)
         -r  use a random name for the erl_call client node
         -s  start a new Erlang node if necessary
         -v  verbose mode, i.e print some information on stderr
         -x  use specified erl start script, default is erl

简单翻译一下:
-a    执行erlang:apply/3,需要提供的就是m f a,m是必须的,f默认值start,a默认值[],注意这个flag只接受一个参数,所以最好通过添加括号把m f a组织起来.
-c 执行cookie值如果没有指定就会使用  ~/.erlang.cookie 文件中定义的cookie,Erlang 节点之间通信必须要有相同的cookie
-d 调试模式;所有的IO都会输出到~/.erl_call.out.Nodename文件,其中NodeName就是我们要处理的erlang节点名;
-e 读一系列的Erlang表达式并返回最后一个表达式的结果,这些表达式用','分隔,'.'结束,这个Erlang Shell是一致的,Ctrl+D组合键结束输入,如果成功返回结果{ok,Result}.
-h HiddenName 隐藏erl_call代表的节点
-m 读入并编译一个module
-n -name -sname 这三个参数三选一,name和n是同样的含义是为了兼容依然保留,sname代码短名称
-q 停止Erlang 节点
-r 为erl_call生一个随机name
-s 必要的话启动一个Erlang的分布式节点,意思是自由第一个调用会启动一个Erlang节点后续的调用就会快很多.
-v  多打印一些冗余信息
-x ErlScript:指定Erlang启动脚本如果不指定就是用erl start-up脚本
 
比如我们现在要获取节点node_1的内存信息
/usr/local/lib/erlang/lib/erl_interface-3.7.6/bin/erl_call -s -a 'erlang memory ' -name node_1@192.168.1.123 -c abc
 
实践中遇到两个问题:
问题一:当name里面包含ip地址的时候执行会报错,这个erlang论坛里面有人也提到了:
erl_call can now use an IP address for remote node name http://erlang.org/pipermail/erlang-patches/2010-October/001533.html
我的解决方案就是把name换成了sname并去掉了ip地址就OK了;
 
问题二:在使用-e参数的时候怎么结束掉输入并查看结果
这个问题的确挺二的,就因为没有仔细阅读文档,结束的时候需要用Ctrl+D,http://www.erlang.org/doc/man/erl_call.html
 
/usr/local/lib/erlang/lib/erl_interface-3.7.6/bin/erl_call -e -name node_1@192.168.1.123 -c abc
A=1,
B=2,
C=A+B.
%Ctrl + D 
{ok, 3}
 
 

SSH

  如果是在没有Erlang的机器接入怎么办?使用ssh即可,直接关闭SSH即可正常退出,如果接入有问题可以添加 -oLogLevel=DEBUG 输出debug信息看一下
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ mkdir /tmp/ssh
$ ssh-keygen -t rsa -f /tmp/ssh/ssh_host_rsa_key
$ ssh-keygen -t rsa1 -f /tmp/ssh/ssh_host_key
$ ssh-keygen -t dsa -f /tmp/ssh/ssh_host_dsa_key
$ erl
1> application:ensure_all_started(ssh).
{ok,[crypto,asn1,public_key,ssh]}
2> ssh:daemon(8989, [{system_dir, "/tmp/ssh"},
2> {user_dir, "/home/ferd/.ssh"}]).
{ok,<0.52.0>}
 
$ ssh -p 8989 ferd@127.0.0.1
Eshell Vx.x.x (abort with ^G)
1>

  

接入Erlang控制台的几种方法的更多相关文章

  1. 网站接入QQ登录的两种方法

    第一种使用系统自带按钮登录,但是这样会弹出新窗口,不喜欢 //调用QC.Login方法,指定btnId参数将按钮绑定在容器节点中 QC.Login({ //btnId:插入按钮的节点id,必选 btn ...

  2. redis 简易监控的几种方法

    简介 针对Redis 实现性能监控的几种方法 一.使用info命令 命令说明 127.0.0.1:6380> info # Server redis_version:3.2.11 redis_g ...

  3. C#中实现并发的几种方法的性能测试

    C#中实现并发的几种方法的性能测试 0x00 起因 去年写的一个程序因为需要在局域网发送消息支持一些命令和简单数据的传输,所以写了一个C/S的通信模块.当时的做法很简单,服务端等待链接,有用户接入后开 ...

  4. 运行jar应用程序引用其他jar包的四种方法

    转载地址:http://www.iteye.com/topic/332580 大家都知道一个java应用项目可以打包成一个jar,当然你必须指定一个拥有main函数的main class作为你这个ja ...

  5. 简要介绍BASE64、MD5、SHA、HMAC几种方法。

    加密解密,曾经是我一个毕业设计的重要组件.在工作了多年以后回想当时那个加密.解密算法,实在是太单纯了.     言归正传,这里我们主要描述Java已经实现的一些加密解密算法,最后介绍数字证书.     ...

  6. iOS获取设备唯一标识的8种方法

    8种iOS获取设备唯一标识的方法,希望对大家有用. UDID UDID(Unique Device Identifier),iOS 设备的唯一识别码,是一个40位十六进制序列(越狱的设备通过某些工具可 ...

  7. Java中获取键盘输入值的三种方法

    Java中获取键盘输入值的三种方法     Java程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值 ...

  8. C#获取当前路径的7种方法

    总结C#获取当前路径的7种方法 C#获取当前路径的方法如下: 1. System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName ...

  9. MySQL命令执行sql文件的两种方法

    MySQL命令执行sql文件的两种方法 摘要:和其他数据库一样,MySQL也提供了命令执行sql脚本文件,方便地进行数据库.表以及数据等各种操作.下面笔者讲解MySQL执行sql文件命令的两种方法,希 ...

随机推荐

  1. VC++ 6.0 BUG BUG BUG BUG BUG

    http://blog.163.com/amao831@126/blog/#m=0 我经常在的VC++6.0中 定义某个类的对象时 再用.访问或者->访问时不自动弹出他的成员函数或者成员变量 最 ...

  2. Codeforces_GYM_100741 A

    http://codeforces.com/gym/100741/problem/A A. Queries time limit per test 0.25 seconds memory limit ...

  3. C#基础数据类型与字节数组(内存中的数据格式)相互转换(BitConverter 类)

      在某种通讯协议中(如 Modbus),可能需要把一些基本的数据类型内存中的表示形式转换成以字节数组的形式,方便传送.C/C++中可以利用指针等操作完成,但C#中没有指针,咋办呢?可以用BitCon ...

  4. 使用H5 formData对象上传图片和视频的文件时,必填的属性

    async : false,cache : false,contentType : false,// 告诉jQuery不要去设置Content-Type请求头processData : false,/ ...

  5. JS学习笔记 - fgm练习 2-5 - 函数传参 设置div样式

    练习地址:http://www.fgm.cc/learn/lesson2/05.html <script> window.onload = function(){ var oDiv = d ...

  6. POJ 1274 The Perfect Stall || POJ 1469 COURSES(zoj 1140)二分图匹配

    两题二分图匹配的题: 1.一个农民有n头牛和m个畜栏,对于每个畜栏,每头牛有不同喜好,有的想去,有的不想,对于给定的喜好表,你需要求出最大可以满足多少头牛的需求. 2.给你学生数和课程数,以及学生上的 ...

  7. 使用stringstream进行类型转换与字符串分割

    C++标准库中的<sstream>提供了比ANSI C的<stdio.h>更高级的一些功能,即单纯性.类型安全和可扩展性. 如果你已习惯了<stdio.h>风格的转 ...

  8. js进阶 13-1 jquery动画中的显示隐藏函数有哪些

    js进阶 13-1 jquery动画中的显示隐藏函数有哪些 一.总结 一句话总结:show(),hide(),toggle(),这三个. 1.jquery动画中显示隐藏效果函数有哪些? show()h ...

  9. 每日技术总结:promise,express route,评分,local storage商品浏览历史,

    最近正在用Vue做一个电商项目.利用工作前后空隙时间. 1.promise的使用 点这里 如何在实际项目中使用Promise 2. Express Route 前后端传参的两种方法 (1)req.pa ...

  10. 9.13 Binder系统_Java实现_内部机制_Server端

    logcat TestServer:* TestClient:* HelloService:* *:S &CLASSPATH=/mnt/android_fs/TestServer.jar ap ...