新建服务器后, 总是要做一些初始化的步骤, 往往需要一些常用的命令. 但是因为这些命令在初始化后基本上就不再用了, 真重新建立服务器了还要去 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字段内的程序所耗费的时间。