新建服务器后, 总是要做一些初始化的步骤, 往往需要一些常用的命令. 但是因为这些命令在初始化后基本上就不再用了, 真重新建立服务器了还要去 Google... 于是记录在这里.
1. ssh
建立好服务器后, 第一件事情是安装 openssh-server.
2. 添加用户
useradd USER_NAME -G GROUP_NAME -d /home/USER_NAME
passwd USER_NAME 来设置用户密码
3. 设置shell程序
chsh -s /bin/bash USER_NAME
/bin/bash 是 bash 的路径. 比如 ksh 就是 /bin/ksh
4. 赐予文件夹拥有者权限
chown /home/USER_NAME USER_NAME
5. 更改用户组
usermod -G GROUP_NAME
usermod 还可以修改其他的东西, 具体 man 一下.
6. 配置 ssh 访问限制
在 /etc/ssh/sshd_config 中添加 AllowUsers USER1 USER2
注意, 用户是空格分开的
7. 更改文件夹拥有组
chgrp GROUP_NAME FOLDER_PATH
有时候需要 -R 如果文件夹有子文件夹.
8. 修改文件夹组权限
chmod g+r/w/x FOLDER_NAME
9. 删除用户
userdel USER_NAME
然后, 配置 apache 啊, exim 啊 或者其他的东西就好啦~
文章《Dynamics CRM 2011编程系列(53):客户端实体序列化工具--MagicBox 》分享了一款序列化实体为JSON字符串的工具,该文章仅仅介绍了如何使用它来生成JSON字符串并没有介绍它的实现原理。本文就来描述下该工具的设计思路以及实现原理吧。
在Dynamics CRM 2011系统中,如果我们想在客户端对记录进行CRUD操作,就现在来说有两种方式:其一为调用REST端点,另一为用JS构造与CRUD对应SOAP报文并发送给服务端。这两种方法我之前都介绍过,今天我们要谈的是第一种方法。
Dynamics CRM 2011中的REST端点是ROA概念的解决方案,ROA即为面向资源。ROA指出互联网上的所有资源都可以用一种格式来进行描述,无论是获取它还是对它进行修改,这种格式就是我们都熟悉的---URI,因此OData就此诞生了。我们看几个OData查询URL吧,这些操作中除Read操作是以GET方式请求请求服务器,其他的均为POST方式。MagicBox生成的JSON字符串主要用在Create和Update操作上。:
Create var path="/GH2011/XRMServices/2011/OrganizationData.svc/ContactSet"; Read var query="/GH2011/XRMServices/2011/OrganizationData.svc/AccountSet?$top=5&$orderby=CreatedOn desc"; Update(需要设置请求报头 X-HTTP-Method的值为MERGE) var uptUrl="/GH2011/XRMServices/2011/OrganizationData.svc/OpportunitySet(guid'{366BE04B-47D9-E011-9C38-000C2956A039}')"; Delete(需要设置请求报头 X-HTTP-Method的值为DELETE) var delUrl="/GH2011/XRMServices/2011/OrganizationData.svc/ContactSet(guid'{366BE04B-47D9-E011-9C38-000C2956A039}')";
MagicBox的Callflow顺序
Click GO button--〉GenerateEntity()--> GenerateSerializationString()
--> GetAttributeMetaData()
-->GetEntityMetadata()
MagicBox中的方法GetEntityMetadata()会根据我们提供的实体名称获取相应的实体元数据,我们在这些元数据中提取我们需要的属性元数据。因为REST端点接受Create/Update提交的JSON字符串是区分大小写的,它是根据属性的SchemaName来进行匹配的。在我们开发的时候我们并不能保证所有的实体的SchemaName都是小写或都是大写,所以很容易出现拼写错误,因此我们很有必要把这个容易出错的环节自动化起来.。
获取实体元数据(只获取当前实体的属性类型的元数据)
private EntityMetadata GetEntityMetadata(string entityName) { if(EntityMetaDataTable.ContainsKey(entityName)==false) { IOrganizationService svc = CommonLibrary.CrmSvcHelper.CreateService(); RetrieveEntityRequest request = new RetrieveEntityRequest(); request.EntityFilters = EntityFilters.Attributes; request.LogicalName = entityName; RetrieveEntityResponse response = svc.Execute(request) as RetrieveEntityResponse; if (response != null && response.EntityMetadata != null) { EntityMetaDataTable.Add(entityName, response.EntityMetadata); } else { return null; } } return EntityMetaDataTable[entityName]; }
光有实体的元数据还是不行的,现在我们还缺少一个对应关系:服务端实体的属性结构和客户端JSON字符串的对应关系。我们可以通过Fiddler抓包来获取这个关系,看官们有兴趣可以自己尝试下,如下是我抓取的对应关系:
{ 'ms_currencytype':{'Value':'1.0000'} --Money Type ,'StateCode':{'Value':'0'} --State Type ,'ms_stringtype':'string type' --string type ,'ms_optionsettype':{'Value':'2'} --picklist type ,'StatusCode':{'Value':'1'} --state reason type ,'ms_floattype':'12.3' --float type ,'OwnerId':{'LogicalName':'systemuser','Id':'f703d401-5a01-e211-90cd-00155db7bf1b'} --owner type ,'ms_decimaltype':'12.5000000000' --decimal type ,'ms_booleantype':'True' --boolean type ,'ms_datetimetype':'4/17/2013 2:34:14 AM' --datetime type ,'ms_lookup':{'LogicalName':'account','Id':'f88a7ff6-74a6-e211-b2be-00155d1ce815'} --lookup type ,'ms_numbertype':'123' --number type }
既然有了这个关系,咱们就可以制作一个解析器了:
private string GenerateSerializationString(Entity entity) { StringBuilder result = new StringBuilder(); string tmp=string.Empty; Microsoft.Xrm.Sdk.AttributeCollection attributes = entity.Attributes; AttributeMetadata attrMetadata=null; result.Append("{"); foreach (var item in attributes) { attrMetadata=GetAttributeMetadata(entity.LogicalName,item.Key); switch (attrMetadata.AttributeType.Value) { case AttributeTypeCode.BigInt: result.Append(string.Format("'{0}':'{1}'", attrMetadata.SchemaName, item.Value)); result.Append(","); break; case AttributeTypeCode.Boolean: result.Append(string.Format("'{0}':'{1}'", attrMetadata.SchemaName, item.Value)); result.Append(","); break; case AttributeTypeCode.CalendarRules: break; case AttributeTypeCode.Customer: break; case AttributeTypeCode.DateTime: result.Append(string.Format("'{0}':'{1}'", attrMetadata.SchemaName, item.Value)); result.Append(","); break; case AttributeTypeCode.Decimal: result.Append(string.Format("'{0}':'{1}'", attrMetadata.SchemaName, item.Value)); result.Append(","); break; case AttributeTypeCode.Double: result.Append(string.Format("'{0}':'{1}'", attrMetadata.SchemaName, item.Value)); result.Append(","); break; case AttributeTypeCode.EntityName: break; case AttributeTypeCode.Integer: result.Append(string.Format("'{0}':'{1}'", attrMetadata.SchemaName, item.Value)); result.Append(","); break; case AttributeTypeCode.Lookup: result.Append(string.Format("'{0}':{{'LogicalName':'{1}','Id':'{2}'}}", attrMetadata.SchemaName, ((EntityReference)item.Value).LogicalName, ((EntityReference)item.Value).Id)); result.Append(","); break; case AttributeTypeCode.ManagedProperty: break; case AttributeType
Linux系统管理员有时候想知道他所管理的机器上的用户正在做什么,Linux管理命令就能帮助我们完成这种工作,我们可以使用Linux管理命令w来实现这一具体的工作,下图反映了运行命令后的文字终端
这个命令可以告诉大家如下信息。
第一行:系统当前运行的基本信息。
在第一行中,总共有三个字段,主要告诉管理员系统当前基本信息。
第一个字段表示时间信息。前面的09:52:36表示系统当前的时间。后面的up 14 days表示距离上次系统重新启动已近共有14天的时间。通过这个参数,管理员可以了解Linux服务器的持续运营时间。这可以给管理员进行系统维护提供帮助。后面的1:45则表示服务器上次启动的具体时间。如果管理员怀疑服务器意外重新启动过,可以通过这个参数来确认。
第二个字段为当前用户登录的总人数。这里需要注意的是,在Linux系统中,同一个账户可以重复登录,因此会见到重复的帐号名称。通常情况下,用户注销登录后,这里的用户总人数会及时更新。
第三个字段主要显示系统当前的平均负载指示。上面三个数值,表示系统在过去的一分钟、五分钟、十分钟内的平均负载程度。通常情况下,其值越接近0表示系统的负载月底,性能也比较佳。
第二行:8个字段显示用户的详细信息。
第一个字段user,显示当前用户登录采用的用户名。这里要注意,Linux系统跟微软操作系统不同。不同的用户可以利用同一个账户进行登录。故如果这里显示两个相同的帐户名的话,不是什么怪事。
第二个字段为TTY,表示该用户登录的终端代号。这个参数对于管理员来说比较有价值。他可以告诉管理员当前用户是通过什么手段登录到系统的。依照用户登录形式的不同,终端代号也有所不同。其中,TTY1-TTY6分别代表本机上的1到6号的虚拟主控台。PTS表示用户是通过远程登陆的。如果数字为:0则表示用户从XWindow登录系统。如上图所示,就表示当前用户是通过远程访问登陆到Linux操作系统的。
第三个字段FROM,显示当前用户从什么地方登录到系统。如果这个字段显示的是“—”符号,则表示当前用户是从本机登录的。如果显示的是IP地址或者主机名称,则表示当前用户是远程登陆的。有时会管理员出于系统维护或者其他方面的考虑,会把这个用户强制踢掉。此时管理员就需要知道当前用户所采用的IP地址。那么就可以利用这个命令来获得。
第四个字段Login,表示当前用户登录的时间。注意这里显示的不是当前用户登录系统的持续时间。他是一个时间点,表示用户登录系统的那个时刻。这个参数往往没有多大的参考价价值。
第五个字段为IDEL。他表示用户登录系统后闲置的时间。这个字段是一个时间段,或者说是一个定时器。只要该用户重新开始工作,则这个定时器就会重新计时。
第六个字段JCPU,表示用户所采用的终端所有相关的程序执行时,所消耗的CPU时间。注意此处的时间并非累加,而是每当工作高一段落之后系统就会停止计时。开始新的工作之后这里会重新计时。也就是说,这里指的是应用程序从开始到结束所占用的CPU时间。
第七个字段与第八个字段,要结合起来看。WHAT字段表示当前用户正在做的事情。如果用户正在执行某个程序,则这里会显示用户执行程序的名字。如果用户正在操作的是执行一般文字模式的命令,则这里显示的是用户的环境名称。而PCPU则表示执行WHAT字段内的程序所耗费的时间。