以下代码在Ruby 186下测试通过
CODE:
require 'sys/proctable'
include Sys
ProcTableps{ |p|
puts ppidto_s if pcomm=='explorerexe' #替换为需要的进程名
}
下载(包括必须的proctablerb):>
一前言
注:因为复制的时候太激动了,所以本文的转载无法经过夏克的同意,这里说声对不住了,希望有人能给个地址,大家上他那去看看!本文在原文的基础上面稍微扩充了RGSS2的知识,但是不多,很多地方都修改了,希望希望夏克同学原谅我,因为我实在没办法联系到你那么,请各位看官阅览本文过后,仔细看看RPG Maker自带的帮助,虽然说是帮助,但是那个也是很好的教材哦!
二基本概念
1什么是RGSS/RGSS 2
Ruby Game Scripting System(以下简称RGSS),中文意思就是:Ruby游戏脚本系统,是一个脚本性质的游戏编程系统,并不是整个游戏都用它来生成,RGSS所能做的只是一些有限的功能,而这些功能,是由厂家也就是EnterBrain所规定的,我们只能在自己力所能及的范围内来挖掘RGSS的潜力,RGSS 2则是在RGSS的基础上扩充和删减了一部分形成的,也可以称之为RGSS的换代版本,是RMVX所使用的
2脚本(Script):
脚本这个概念应用的范围很广,Windows系统里就有VBScript,JavaScript,WScript等脚本程序,Unix系统也有很多Perl,C等脚本程序,脚本可以解释为是一种系统内用来实现一些特定功能的有着局限性的编程环境有的脚本可以触及到系统底层,有的却只是完成一些运算或者控制流程的功能,这取决于脚本系统的权限,也可以说取决于脚本系统所提供的库函数功能
3RGSS/RGSS2中的脚本:
在RPG Maker XP/RPG Maker VX(以下简称RMXP/RMVX)中,按F11就可以打开[脚本编辑器],不过RM2003或更早的版本却没有这个功能,左边的窗口是脚本列表,右边的窗口是脚本内容,左下角可以修改脚本名称
在RMXP/RMVX中,游戏开始运行后,总是从最上边的脚本开始运行,依次往下,所以,经常把变量声明、类声明、函数声明、函数定义的脚本放在上面,而MAIN脚本总是放在最后
三开始神奇的脚本学习旅程
1Hello,World!
经过上面的基本知识后,相信你对RGSS/RGSS2的相关知识有了一定了解,一般的编程语言教程都是从"Hello,World!"开始的,那好,我们也从"Hello,World!"开始,不过为了体现RGSS语言与Ruby的不同,我们将其改为"Hello,World,我来学习RGSS语言了!",首先,请打开RMXP/RMVX,在新建好一个空白工程后,按下键盘上面的"F11"键,开始我们的RGSS/RGSS2脚本学习之旅!为了保证执行脚本的快速,请在脚本列表中选中最顶端的那个脚本,然后按下方向键上面的Delete(也称为DEL、删除)键,删除脚本直到Main脚本为止(这里的意思是只保留Main脚本),选择[插入]来插入一个新的脚本,给新脚本命名为Test,删除Main脚本,点[确定]这样我们就得到了一个空的脚本系统,试着运行一下游戏,可以看到游戏在短暂的启动后就自动终止了,这表明没有任何脚本可以执行,游戏只好退出既然测试成功了,那么下面我们在Test脚本中加入一些内容按F11打开[脚本编辑器],因为我们只有Test一个空脚本,所以在Test的内容中输入下面的代码:
p "Hello,World,我来学习RGSS语言了!"
把这行代码复制并粘贴在Test脚本中,按[确定],按F12,保存后游戏开始运行,短暂停顿后就会d出一个对话框,内容是不是:"Hello,World!"这样我们就做出了第一个脚本,如果是学过Ruby的你一定会发现中文会被正常的输出,而不是类似于"/数字/"的结果,但是这里要说的是,RGSS不支持puts命令,而printf命令则会忽略掉,如果您实在怀恋,可以通过其他的脚本来辅助实现值得说一下的是,RGSS是会区分大小的,所以这里的p不能使用P(大写的P)
2脚本的注释
在学习任何语言的过程中,注释是少不了的,因为注释不仅仅可以让新手更明白脚本语句的含义,而且还会使脚本看起来更整洁、美观,当然,能做到的当然还有很多在RGSS中,有两种注释,它们分别是符号 # 和
=begin
=end
如果你比较细心的话应该可以看出他们的用途, 符号#是用来注释单行,而 =begin =end 是用来注释多行的,在这里,有个知识点需要提一下,符号#后的脚本是会被忽略的,也就是说,你把符号#插入到某一脚本的前面,那么那条脚本就会无效,很多人都将在脚本前添加#看做是一种解决脚本故障的办法(也就是DEBUG),举个例子:
p "Hello,World,我来学习RGSS语言了!" #我是很可爱的注释,执行脚本的时候你会无视我!
将这段代码插入到脚本中,#后面的语句或者注释将被无视,然而在这段代码中,无论是什么都会无效
=begin
p "Hello,World,我来学习RGSS语言了!" #我是很可爱的注释,执行脚本的时候你会无视我!
=end
到此,基础部分完毕,如果你想要学习更深入的知识,请往下看
四数据类型
1数字
数字包括整数和小数,小数在计算机术语中被称为浮点数,相信大家都明白什么是整数和小数了整数包括正整数和负整数,0可以被视为整数,数字属于常量的一部分
常见的数字种类有:
1 = 整数
100 = 整数
-10 = 整数
0 = 整数
011 = 浮点数
-123 = 浮点数
那好,让我们写一个脚本来学习如何显示一个常量的值,在Test脚本中,清除脚本内容,插入下面的代码:
p 100
运行游戏,看到d出的对话框显示:"100",若输入我们输入:
p 100100
作为新手的你觉得会d出什么呢,想想,实际上d出的是1001,而不是100100
2数字的计算
我们在上节讲了数字的类型与输出给用户的方法,现在我们来体验一下数字的计算,在脚本 TEST 中插入以下代码:
p 1+1
运行游戏,看到d出的对话框显示:2这就是常量的加法你可以很聪明地想象出乘法、除法、减法:
p 3+5
p 35
p 3/5
p 3-5
运行游戏,你会发现游戏按脚本顺序输出了加、乘、除、减,你会发现,3/5输出的是0而不是正确结果,整数和整数的运算,其结果仍旧表现为整数,如果你希望得到浮点数,那么就应该使被除数或者除数至少有一个是小数形式的表示请看下面的代码:
p 30/5
p 3/50
运行游戏,显示的结果就都是小数了值得一提的是还有两个很有用的算符,求余数(%)和乘方(),输入以下代码:
p 14%4
p 23
它们分别输出了2与8,和预期的正确结果一样
3括号的用处
各种运算符之间总会存在优先顺序,加减乘除的顺序是不变的,对于其它你所不熟悉的或者弄不清除的,只要记住一点就可以了,那就是括号的优先权是最高的,善用括号能够至少确保程序的准确性而先不管是不是很难看,当然,强大的RGSS所使用的基本不是只有一个功能,或考得其他功能我们会在以后的章节一一阐述
4 常量与变量
常量:常量就是我们经常会用的数字、字符串了,比如我们问一张光盘多少钱,回答说5元,那么5就是常量,如果说一张光盘的价格不定,在3-5元的范围内浮动,那么这就是我们学过的未知数,对于这样的未知数我们经常会用一个变量来表示
变量:变量就是我们用一个符号来表示一个我们想要表示的概念,比如我们可以用price这个变量来表示一张光盘的价格变量与常量的区别就在变量是可以变动的,也就是说我们用变量来定义一个概念后,接下来就会来 *** 作这个变量使它变化而我们不能让一个常量变化,比如我们不能让5=4,但我们可以让price=4
命名规则: 变量的取名有以下的限制:
1、必须以英文字母(大小写均可)、汉字、下划线开头
2、第二个字符开始可以使用数字、英文字母、汉字、下划线
3、不能使用保留字作变量的名字
保留字是保留给系统用的,也就是说系统已经占用了,以下是系统的保留字:
alias def false nil return unless
and do for not self until
begin else if or super when
break elsif in redo then while
case end module rescue true yield
class ensure next retry undef
所以不要使用上面列出的单词做你的变量的名字
变量的赋值:变量无需事先声明,可以拿来就用,例如:
a=100
p a
运行脚本,看到d出的对话框显示:100 , 但必须先赋值才可以使用变量,否则,试试下面的代码:
p b
会d出什么呢,如果不赋值给变量,就相当于这个变量不存在,而一旦赋值给它,就表明这个变量存在了
变量的运算:
下面的代码你应该可以猜出是什么结果的:
战斗前的体力=234
战斗后的体力=200
p 战斗前的体力
p 战斗后的体力
继续:
p 战斗前的体力-战斗后的体力
看到了吗,这里我进行了运算,变量的运算
就像对于常量一样,加减乘除和括号同样适用于变量的运算:
x=1
y=2
z=3
p x+(yz)/(y+z)-y+z
但下面的运算是常量所没有的:
自运算:
x+=5
y=2
z/=3
p x
p y
p z
+=,-=,=,/=这四个运算符是自运算符,x+=1相当于x=x+1,其它同理
全局变量:
局部变量和全局变量的区别在于局部变量只能被所在的脚本访问,而全局变量能被所有的脚本访问
在变量名前加$符号就可以声明全局变量了
5 字符串
显示字符串:
先看看下面这几行语句在RGSS中的效果:
p"这将会显示双引号"
p'这也会显示双引号'
print"这不会显示双引号"
print'这也不会显示双引号'
把上面的四行语句复制下来,然后在我们刚刚建立好的Test脚本中粘贴,粘贴前最好把Test脚本的内容清除掉,我们只需要测试我们现在的代码好,运行游戏,看看效果吧
首先,看得出来,用来输出显示的方法又多了一种:print,不同的是,p可以显示很多种数据类型,对不同的数据类型,它会按人们容易理解
的格式来显示,比如说这里的字符串,它都会加上双引号来告诉人们:这次显示的是字符串,而print直接显示字符串本身
在上面的代码中,分别输出下面的四行字符串:
"这将会显示双引号"
"这也会显示双引号"
这不会显示双引号
这也不会显示双引号
6字符串常量:
字符串常量的表示有两种方法
1双引号表示的字符串:
这种表示方法使得字符串可以支持一些特殊格式,这将是我们用的最多的表示方法,下面会有更详细的介绍
2单引号表示的字符串:
直白的说,单引号所包括的字符串会被原样显示出来,也就是说,即使单引号中包含特殊格式,也不会显示这种特殊格式
7字符串变量:
和数字变量一样,看看例子吧:
1、赋值:
a="欢迎使用RGSS来编程"
print a
结果输出:欢迎使用RGSS来编程
2、连接:
a="中华人民"
b="共和国"
print a+b
结果输出:中华人民共和国
3、乘法:
a="连续两遍"
print a2
结果输出:连续两遍连续两遍
4、换行符:
\n表示换行,但是只能用在双引号字符串内,若是在单引号字符串内便不起作用了,看看下面两个例子:
a='中华人民\n共和国'
b="中华人民\n共和国"
print a
print b
结果输出:
中华人民\n共和国
中华人民
共和国
5、常量中包含变量:
a="人民"
print "中华#{a}共和国"
结果输出:中华人民共和国
记住:这个特殊格式和\n一样只能在双引号形式的字符串中使用,这里提一下,这里的#符号不是注释的意思
再看一个:
a="C:\\Program Files\\RPG Maker XP\\System\\Data\\Skillsrxdata"
print "系统安装后的初始脚本文件是:#{a}"
你可以试试看下面的例子:
a="人民"
print '中华#{a}共和国'
结果输出:中华#{a}共和国
五 控制语句
1 条件分歧语句
1比较运算符:
有6个比较运算符,分别是
== 相等
!= 不相等
< 小
> 大
<= 小或相等
>= 大或相等
比较运算符,顾名思义,就是用来比较的,比较的对象可以是任意的,比较的结果是True或者False
举例:
p(" 早安 "==" 早安 ") # => true
p(" 早安 "==" 晚安 ") # => false
p (3 + 1 == 3 + 5) # => false
p (3 + 1 == 2 + 2) # => true
观察一下结果就会明白
逻辑运算符:
逻辑运算符也有6个,分别是:
与:and , &&
或:or , ||
非:not , !
举例:
p (100 > 77 and 1 + 1 == 2) # => true
p (100 > 77 && 1 + 1 == 2) # => true
ifelseifelseend 语句:
结构:
if 条件1
语句1
elseif 条件2
语句2
else
语句
end
举例:
x=123
y=23
z=67
a=(xyz+x/y+z/y)(y-z)+xz
if a>0
print "大于0"
elseif a=0
print "等于0"
else
print "小于0"
end
最常用的还是ifend语句:
金钱数=10
if 金钱数<100
print "对不起,你的钱不够了"
end
unlessend 语句:
这是ifend语句的变种,正好跟ifend相反,就是除非的意思:
unless 条件
语句
end
举例:
金钱数=10
unless 金钱数>=100
print "对不起,你的钱不够了"
end
除非你的金钱数大于等于100,否则:“对不起,你的钱不够了”
casewhenend 语句:
如果对于把条件限制在某个范围或者某些特定的值的情况,使用caseend语句更方便:
case 变量
when 特定的值或者范围
when 特定的值或者范围
end
举例:
主角状态="昏睡"
case 主角状态
when "昏迷"
print "你昏迷了"
when "中毒"
print "你中毒了"
when "昏睡"
print "你昏睡了"
end
2条件赋值语句:
条件赋值语句给我们提供了一个非常方便的ifelseend的简化版
(条件1 语句1 : 语句2)
相当于:
if 条件1
语句1
else
语句2
end
举例:
战斗状态=1
print (战斗状态>0 "胜利" : "失败")
2循环
1whileend 循环:
举例:
a = 0
i = 1
while i <= 5
a += i
i += 1
end
p a
这很简单,很容易明白的
2forinend 循环:
类似于c语言中的for,但不同,in后面给出变量的变化范围
3变化范围:
类似于15表示一个变化范围,其所含的值为大于等于1小于等于5
举例:
a = 0
for i in 15
a += i
end
p a
这也很简单,很容易明白的
4loop doend 循环:
举例:
i = 0
loop do
i += 1
p i
end
上面的代码会一直循环下去,也就是说是个死循环只有使用break才可以从中跳出
5break 语句:
上面的例子如果改成下面的样子,就不再是死循环了:
i = 0
loop do
i += 1
if i == 5
break
end
p i
end
break也可以从while、for循环中跳出
6next 语句:
跳过本次循环,进入下次循环
举例:
for i in 15
if i == 3
next
end
p i
end
结果显示四次,就只有1,2,3,4,5被显示出来了
3 函数
1 函数的概念:
我们把事先编好的,能够解决或者说处理某种情况的功能的集合叫做函数不必在意概念,用得多了自然就明白其实我们一直在使用的
p,print就是函数的一种,下面介绍一个很有用的函数,随机函数rand():
rand(x)返回0-(xx-1)范围内的随机数,例如:
p rand(100)
返回的数字在0-99范围内
我们也可以设计自己的函数以便增加我们需要的功能,更多的时候,我们大多数时间是在跟函数打交道
2 函数的声明:
函数的名字基本上和变量的名字有着相同的限制,例外的情况是,函数可以在名字的最后添加或!符号,这种符号有着特殊的用处,以后会讲到
函数的声明要用defend语句,形如:
def 函数名字
语句
end
我们用rand函数来设计一个自己的函数bet():
def bet
if rand(6)>3
return "大"
else
return "小"
end
end
print bet
这里的return表示函数返回的值,如果省略return也可以,但最好带上,能够使程序可读性更好
我们给bet函数增加参数:
def bet(x)
if rand(x)>3
return "大"
else
return "小"
end
end
print bet(7)
还可以为参数设置默认值:
def bet(x=7)
if rand(x)>3
return "大"
else
return "小"
end
end
print bet #这和print bet(7)一样
函数可以有很多参数:
def bet(x,y,z)
if rand(x)>3 and rand(y)>3 and rand(z)>3
return "大"
else
return "小"
end
end
print bet(7,6,10)
4 重定义函数:
如果定义了两次相同的函数,则只有后面定义的函数有效,而先前的定义就无效了
def hello
return" 您好 "
end
def hello
return" 晚安 "
end
p hello #=>" 晚安 "
六 数组
如果知道将多次对一个变量,例如 $salut赋值,您会怎样做呢?这在很多情况下都会发生因此,您可以将所有的变量值放进一个数组里,而不是手动
地给变量重新赋值
数组允许对每个变量值进行分别的处理请看如下示例:
$salut = ['Hello World','Good Bye World','What do you mean Good Bye World'] print $salut
运行上述代码得到的输出如下所示:
Hello WorldGood Bye WorldWhat do you mean Good Bye World
显然,这不是我们想要的输出没有间隔也没有换行因此,我们可以标识希望显示数组的哪一部分,并使用先前解释的串联技术来更方便地提供易读的输出
$salut = ['Hello World','Good Bye World','What do you mean Good Bye World']
print $salut[0] + "\n"
print $salut[1] + "\n"
print $salut[2] + "\n"
将会导致如下输出:
Hello World
Good Bye
World What do you mean Good Bye World
仔细分析这些代码如果回顾一下我们建立的数组:
$salut = ['Hello World','Good Bye World','What do you mean Good Bye World']
我们告诉 Ruby 定义一个名为 salut 的变量,其值为:
$salut = 0 1 2
Hello World Good Bye World What do you mean Good Bye World
每个值通过一个数字来被识别数字通过数组中的数字位置来定义位置总是从 0 开始,并从 0 开始递增所以要打印数组中的第 2 个值,
您要输入:
print $salut[1]
最容易忘记的是字段从 0 而不是从 1 开始
七 load,require语句
在许多知名网站上,很多的人都认为RGSS不支持load,requir,语句,如果需要使用的话好去破解Scriptsrxdata文件(XP)或者Scriptsrvdata(VX),其实你不用去研究破解Scriptsrxdata了,因为RGSS完全支持load,require语句,只不过与Ruby语言稍有区别的是这两个语句只支持绝对地址,也就是说不支持类似于:require "win32/" 的格式
在我们的试验脚本中输入:
load "d:/sequhrb"
就可以加载D盘的sequhrb文件了,同理:
require "D:/sequhrb"
这里我输入的是绝对路径,绝对路径的表示方法是:
把DOS格式的路径名中的“\”统统改为“/”即可
而相对路径的获得,需要一点儿办法:
因为在我的游戏目录下有gameexe文件,所以我们可以通过它来获得游戏目录,然后得到绝对目录,把我们的相对路径加到绝对目录后面,例
子:
load "#{Filedirname(Fileexpand_path("Gameexe"))}/scripts/sequhrb"
其中的Filedirname(Fileexpand_path("Gameexe"))便是游戏目录的绝对路径
八 对象和方法
这个代码段中用到的一些技术和方法您可能是第一次见到RGSS是一种面向对象的编程(Object Oriented Programming,OOP)语言使用 OOP 时,通常情况下程序员将调用诸如对象和方法之类的项目对象就象一个容器它包含自己特定的变量和函数 方法是一种被调用的东西,就像函数对对象进行专门处理一样如果看一下先前的示例,我们就可以显示工作中的对象和方法
while enterWorld = STDINgets enterWorldchop!
这里我们有两个对象和两个方法的示例第一个对象是 enterWorld,第二个对象是 STDINenterWorld 对象是用户定义的对象,而 STDIN 对象(Standard Input 的缩写)是RGSS内建的
这个示例中还有两种方法第一种是 gets,第二种是 chop!前面提到过,方法对对象进行专门处理明确地说,方法将在对象中执行一个 *** 作用 gets 方法,我们告诉 RGSS 去获取 STDIN当 RGSS 看到与 STDIN 关联的 gets,它就会等待键盘输入和一个回车简而言之,STDINgets 就是等待用户输入一些内容然后敲 Enter 键
第二种方法 chop! 用来对用户定义的对象 enterWorld 进行专门处理chop! 方法告诉 enterWorld 将 enterWorld 对象关联的数据的换行符
和回车符截去如果不使用 chop!(或者 chomp!),那么包含在先前代码上下文中的下面语句永远都不会为真
if enterWorld == $salut[0]
因为没有使用 chop!,所以得出结果将为假,$salut[0] 实际上就等于 $salut[0]\n新行是由 STDIN 对象从 gets 方法接收的输入产生的使用回车将会在值末尾添加一个换行符
autoit和按键精灵 按键娃娃这些属于按键工具 可以模拟控制
ruby,lua,php,python vb60,C#,java erlang等这些可以模拟控制
C/C++ 汇编 可以控制硬件键盘鼠标
ruby判断字符串用"=="就可以。判断对象可以用"equal"方法。此处与java相反。
p str1==str2返回的结果应该是先打印"str1==str2"的结果后,然后再输出一个空行。这点可以查看相关api。所以msgbox显示的是nil(即返回的空行)。
测试实例:
irb(main):002:0> s=p "1"=="1"
true
=> nil
irb(main):003:0> s
=> nil
创建目录,copy配置文件
如何安装Redis集群
修改配置文件
按照此方式修改7001~7005的配置文件,注意修改端口号。
如何安装Redis集群
启动各个实例
如何安装Redis集群
创建集群
现在我们已经有了六个正在运行中的 Redis 实例, 接下来我们需要使用这些实例来创建集群, 并为每个节点编写配置文件。
通过使用 Redis 集群命令行工具redis-trib,编写节点配置文件的工作可以非常容易地完成redis-trib位于Redis 源码的src文件夹中,它是一个 Ruby 程序,这个程序通过向实例发送特殊命令来完成创建新集群,检查集群,或者对集群进行重新分片(reshared)等工作。
我们需要执行以下命令来创建集群:
[root@localhost src]# /redis-tribrb create --replicas 1 127001:7000 127001:7001 127001:7002 127001:7003 127001:7004 127001:7005
/usr/bin/env: ruby: No such file or directory
如何安装Redis集群
系统中没有安装ruby,所以报上面的错误。
先安装ruby
[root@localhost yumreposd]# yum install ruby
[root@localhost yumreposd]# yum install rubygems
[root@localhost yumreposd]# gem install redis
Successfully installed redis-322
1 gem installed
Installing ri documentation for redis-322
Installing RDoc documentation for redis-322
如何安装Redis集群
再次创建集群
[root@localhost src]# /redis-tribrb create --replicas 1 127001:7000 127001:7001 127001:7002 127001:7003 127001:7004 127001:7005
Redis自动选择主从
如何安装Redis集群
连接集群
redis-cli 也可以作为集群的客户端工具,要想访问集群,只需连接任意一个redis实例即可。使用-c参数
[root@localhost bin]# /redis-cli -c -p 7000
总结
set 命令写数据,集群将数据写到7001实例上,当你使用get命令获取数据时,客户端即自动切换到7001端口。
redis-cli对集群的支持是非常基本的, 所以它总是依靠 Redis 集群节点来将它转向(redirect)至正确的节点。一个真正的(serious)集群客户端应该做得比这更好: 它应该用缓存记录起哈希槽与节点地址之间的映射(map), 从而直接将命令发送到正确的节点上面。
这选择显然是因人而异的。。至于怎么选,要看你是初学者,还是老手?。。对性能有要求,还是没要求?
如果是完全没有基础,我建议哪个都不选,如果非要选一个,那就选PYTHON。。如果你是初学者,把网上的教程看个遍,再买上几本书。。。你所学会的也仅仅是语法,而根本不会编程。。。因为这些教程,也仅仅是教你语法,而没有教你编程。。你甚至把网上的教程看个精光,却连个最基本的OA系统都做不出来。。。只能在一个黑乎乎的控制台上,打印一堆破字符。。
-------网上的所有教程都会教你的:
怎么定义一个变量?怎么在控制台打印变量?
怎么写一个循环?怎么在控制台打印一堆变量?
怎么写一个函数?怎么在控制台打印返回值?
怎么创建一个对象?怎么在控制台打印对象属性?
------高级一点的教程,会教你的:
怎么用PYTHON的模块,写一个爬虫?
怎么用RUBY的ROR框架,获取一个表单?
怎么用GO的beego,写一个博客?
-------而这些的教程,从来不教你的:
面向对象有什么用? 委托是什么?事件是什么? 工厂模式,单例模式,观察者模式,这些都是啥?套接字是啥?UDP是啥?TCP/IP是啥?二叉树是什么玩意?状态机又是什么玩意?啥叫逆变?啥叫协变?啥叫异步?啥叫反射?
---------------------------------------------------------------------------------------------
如果一套教程,要把这些都讲明白。。。可能需要上千集。。。所以这些教程,都跳过了这些内容。。但如果你不明白这些,就根本学不会编程。。。如果你打算学一门语言,而手上只有几十集教程,外加三五本书。。。那你只能学会玩控制台。。。
所以初学者选择一门语言,首先要保证这门语言作为主要开发语言,常年被公司使用,这样才能真正学会编程。然而这三门语言都不具备这样的特点。它们通常都是被当成第二语言,做一些辅助开发的工作。其中Python只在极少数情况下,才被用来作为主要开发语言。至于Go与Ruby,我目前还没听说过它们有被当作主要开发语言的例子。我所推荐的是从C#和JAVA两者之间,二选一。。。学精其中一门之后,再来考虑PYTHON或GO作为第二语言。。。不然无论你选哪个,都几乎不可能靠一门语言找到工作。
最近在解决探针获取Ruby应用服务器的内存使用的情况,将解决的思路总结一下,希望对此感兴趣的伙伴一起探讨。
先对比应用服务器: Puma 和 Passenger ,下面对比这2个服务器内存统计,
单进程模式:直接获取进程id: Processpid
cluster模式:以启动2个worker进程为例:
从上面截图可以看到,Puma启动后会出现3个进程:1个master进程和2个worker进程。
内存的使用情况(见 RSS 列):
而对于探针来说,一个探针实例是伴随进程一起启动的,也就说一个探针只能识别自己所在的进程id,那如何获取应用服务器使用的内存?我们用其中1个woker进程所在的进程组[ PGID ]看一下:(为啥不是父进程, 见下文Passenger)
这3个进程都在相同的进程组里,而且进程组号为master的进程id,那我们就可以用这个信息获取应用服务器的所使用的内存:
4累加进程组内进程内存和即为应用服务器使用内存:
启动Passenger后的Process信息:
对Passenger架构感兴趣的请移步到 这儿
查看一下worker所在进程组和父进程:
通过PPID可以看出
Passenger core —> Passenger AppPreloader —> Passenger RubyApp
三者为爷-父-子关系,当服务器请求量增大时 AppPreloader 会产生新的进程来响应请求,从而新的 RubyApp 进程的 PPID 即为 AppPreloader 的 PID ,这样看来就可以将同一个 PPID 的进程加起来得到应用服务器的内存?
由于Passenger会根据服务器的负载量动态调整进程数,当服务器请求量较小时,Passenger会kill多余的进程,会出现下面的情况:
AppPreloader 也被Passenger杀掉了。原 RubyApp 进程的 PPID 变成了1。这时如果服务器的请求量增大,应用服务器进程会成为这样:
Passenger core 产生新的 AppPreloader 进程,并且 AppPreloader 产生新的 RubyApp 进程,这时如果只用 PPID 统计应用服务器内存就会不准确,所以要统计Passenger的使用的内存还得通过累加在同一个进程组( PGID )的所有进程使用的内存和得到。
由于 Unicorn 和 Rainbows 都与Puma的cluster模式[master+worker模式]类似,内存统计的方式可以参考上文的Puma。
由于 Thin 启动多个server后没有类似的特点,上面方法不适用于Thin,有好方法的伙伴们可以告知:smile:
在解决探针统计应用服务器的内存问题上,摸索出了上面的一条路子,如果小伙伴们有其他更好的方式,可以一起探讨一下。
以上就是关于Ruby获取进程ID的问题全部的内容,包括:Ruby获取进程ID的问题、安装selenium webdriver ruby版的时候无论是线上安装,还是gem包下载下来安装都出现错误,求解决、Ruby模拟键盘输入字符串等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)