集群管理工具Salt
集群管理工具Salt
简介
系统管理员(SA)通常需要管理和维护数以百计的服务器,如果没有自动化的配置管理和命令执行工具,那么SA的工作将会变得很繁重。例如,要给集群中的每个服务器添加一个系统用户,那么他必须登陆到每台服务器上去逐一的执行命令。好在有编程能力的SA能通过bash + ssh的方式来自动化自己的工作,于是出现了ClusterShell这一类的工具。但这类工具只是解决了远程命令调用的问题,并没有对一些运维的过程进行抽象,在面对不同的操作系统等环境时,使用会变得复杂和繁琐,对常见的运维操作,如包管理、配置文件分发也没有很好的支持。于是出现了CFEngine,Puppet,Chef,Salt等工具,他们在远程命令执行的基础上对一些常见的运维操作进行了抽象,如节点分组、命令编排、状态管理等。
Salt正是其中年轻一员,它是一个使用Python和ZeroMQ开发的开源项目,使用Apache 2.0 License。Salt的主要功能有两个:1)配置管理,使节点处于所定义的状态,如指定web类节点apache包的状态为安装并运行;2)分布式的命令执行系统,一方面分发命令到节点执行,另一方面从节点收集所需的数据。
特点
(翻译自官方介绍http://salt.readthedocs.org/en/latest/topics/index.html)
1)简单
salt能适用于不同规模的部署,安装和维护都很简单。
2)并行执行
- 由master向Minion发出的命令是并行执行的,而不是串行;
- master与Minion之间的使用加密的协议;
- 尽可能的使网络负载降低,提高网络传输效率;
- 提供简单的编程接口;
3)基于成熟的技术
- 使用ZeroMQ进行网络通信;
- 使用AES对通讯进行加密;
- 使用msgpack作为数据序列化的格式;
4)快、灵活、可扩展
架构
Salt主要由三个部分组成:
- salt-master:安装有salt-master的节点我们称作Master节点,它负责存储配置信息、对可信的Minion节点进行授权、通过ZeroMQ与Minion节点进行交互。
- salt-minion:安装有salt-minion的节点称作Minion节点,salt-minion就是一个agent进程,通过ZeroMQ接收来自master的命令,执行并返回结果;
- salt-syndic:在特别庞大的部署环境中才会使用syndic,比如在多数据中心的部署中。syndic相当于一个正向代理节点,它代理了所有Master节点与Minion节点的通信。这样做一方面可以将Master的负载分担给多个syndic承担。另一方面,它也可以降低Master通过广域网访问Minion的成本,提高了安全性,使salt适用于夸数据中心的部署。
快速体验
http://docs.saltstack.com/topics/tutorials/walkthrough.html
体验的步骤如下:
- 为各个节点配置fqdn,并确定各个节点之间能通过fqdn互相访问,其中master节点的fqdn为salt(因为Minion节点启动后会默认向salt注册信息);
- 安装salt,master节点安装salt-master,Minion节点安装salt-Minion;
- 确保防火墙关闭或打开指定的端口,salt-master主要使用4505和4506端口;
- 在master节点使用salt-key对Minion进行认证;
- 尝试运行命令;
核心功能
Targeting(批量操作)
批量操作是指master将选取哪些minion执行命令或同步master指定的状态。salt提供了几种方式来选取执行操作的Minion,它们分别是:
这种方式是基于匹配minion_id,minion_id在默认情况下是minion节点的fqdn。匹配的方式支持正则表达式、通配符、列表,如:
- salt ‘*' test.ping //选取所有的minion执行test.ping命令
- salt -E 'web1-(prod|devel)' test.ping //选取web1-prod或web1-devel去执行命令
- salt -L 'web1,web2' test.ping //选取web1和web2
- salt ‘web*' test.ping //选取所有以web为前缀的节点执行
Grains是指minion节点注册时master节点所收集的信息,比如操作系统、CPU架构等。salt也可以基于grains信息来选取执行命令的minion节点,例如:
- salt -G 'os:Ubuntu' test.ping //选取所有操作系统是ubuntu的minion节点执行test.ping命令
可以使用salt -N 从配置文件中读取指定的分组执行命令;
可以使用salt -C 来组合使用上面提到的三种匹配策略,例如:
- salt -C '* and not G@os:Ubuntu' test.ping //选取所有操作系统不是Ubuntu的节点执行test.ping
通过-b参数从已匹配的节点中再次筛选指定数量的节点执行命令,例如:
- salt ‘*’ -b 25% test.ping //从所有节点中选取25%执行命令
Remote Execution(命令编排)
按字面意思理解,这个核心功能可以称作远程调用或者远程执行。但是中文的专业术语会翻译成命令编排,这其中的原因我想是因为“编排”这个词能体现在minion端所执行的命令是逻辑有序的。salt提供了很多功能不同的模块实现了日常的运维工作,这些模块编排了常用的运维指令和逻辑,而master能远程调用他们完成相应的功能。例如,test.ping完成了测试minion节点是否存活,bridge.add 会添加网桥设备。
了解完这个核心功能后,salt的命令格式也变得清晰
- salt [TARGETING] [COMMAND] [ARGS]
TARGETING指出了谁去执行命令,COMMAND和ARGS指出了执行什么命令以及命令的参数。其实后面讲到的状态管理也是基于这两个核心功能构建。此外用户还可以自己写模块,对salt的功能进行扩展。
States(状态管理)
状态管理也通常被称作软件配置管理(SCM, Software Configuration Management)。状态管理程序会使让的系统保持或到达预先定义的状态,他会依据状态的描述,安装软件包、打开或重启服务或将配置文件分发到指定的位置并监控它的变化。
拥有状态管理,SA可以很轻松的管理数百台或数万台的服务器配置。将状态管理的配置文件放置在版本管理工具(git, svn)下,能很好的管理配置的变更。
Salt States是Salt的配置管理工具。如上文所述,它本质上是Remote Execution的一个模块。master通过命令编排调用minion上的state模块,触发minion从master获取状态描述文件(SLS文件)并按照描述文件的描述执行相应的操作。
SLS文件可以静态的描述minion的状态,也可以通过Grains和Jinja模板动态的生成状态描述,状态描述之间也存在着不同的关系。可以参照下面的文章深入的学校Salt的状态管理。
http://thinkinside.tk/2013/06/25/salt_usage.html
http://salt.readthedocs.org/en/latest/topics/tutorials/states_pt1.html
http://salt.readthedocs.org/en/latest/ref/states/index.html
其它功能
Salt还提供了很多的扩展功能,如Returners提供了不同的存储后端保存minion返回的数据,salt cloud添加了对AWS等公有云的支持等。
小结
本文简单首先介绍了系统运维的需求和运维工具的基本情况,因为我不是专职的运维人员总结的比较笼统;然后介绍了Salt的架构和核心功能。其实只要在宏观上对Salt有一个基本的认识“它是干什么的,怎么干的”,那么以后无论是使用Salt还是基于Salt做开发都会有思路了,遇到问题查阅官方手册基本都能解决。
要熟悉Salt的使用,动手实践是必不可少的。我还会记录一些在Vagrant上使用Salt的过程,也会尝试使用Salt、vagrant去部署一个OpenStack环境。
相关资源
http://thinkinside.tk/pages/tags.html#salt-ref
http://salt.readthedocs.org/en/latest/ref/states/index.html
目录
背景常见的状态机需求实现状态机一个简单的示例一个相对完善的例子实现代码进一步交代的问题备注
背景返回目录
企业应用下,需要关注三个状态机:
- 业务相关的状态机。
- 审批流程相关的状态机。
- 持久化相关的状态机。
某些企业应用开发人员终其一生就是希望能开发出通用的一个框架以简化这些状态机的开发。本文重点关注:“业务相关的状态机”。
常见的状态机需求返回目录
产品的状态机
单据的状态机
业务相关的状态机的一般性需求如下:
- 当处于某个状态时,可以执行哪些合法的迁移?迁移的前置条件是什么?
- 当处于某个状态时,可以执行哪些合法的操作?如:已提交和已审核状态的单据不能被修改。
实现状态机返回目录
我目前使用过两种思路实现这种状态机:
- 使用状态模式。这种要求为每种单据的状态管理定义一套状态体系,有点麻烦了。
- 使用状态表格。这种就是本文介绍的。
下面先看两个示例。
一个简单的示例返回目录
注意下面的链式配置代码,这些代码表达的意思是:
In(Status.UnSaved).When(Operation.Save).If(CanSave).TransferTo(Status.Saved)
处于 UnSaved 状态下,当 Save 操作发生时,如果 CanSave,就迁移到 Saved 状态。
------------------------------------------------------------------------------------
.In(Status.UnSaved).When(Operation.Edit).Aways().Ok()
处于 UnSaved 状态下,当 Edit 操作发生时,总是,允许的。
代码
- 1 class Order
- 2 {
- 3 private readonly StateMachine<Status, Operation> _stateMachine;
- 4
- 5 public Status Status { get; internal set; }
- 6
- 7 public Order()
- 8 {
- 9 _stateMachine = StateMachine<Status, Operation>
- 10 .Config(() => this.Status, status => this.Status = status)
- 11 .In(Status.UnSaved).When(Operation.Save).Aways().TransferTo(Status.Saved)
- 12 .In(Status.Saved).When(Operation.Submit).Aways().TransferTo(Status.Submitted)
- 13 .Done();
- 14 }
- 15
- 16 public void Save()
- 17 {
- 18 _stateMachine.Schedule(Operation.Save);
- 19 }
- 20
- 21 public void Submit()
- 22 {
- 23 _stateMachine.Schedule(Operation.Submit);
- 24 }
- 25
- 26 public void Edit()
- 27 {
- 28 _stateMachine.Schedule(Operation.Edit);
- 29 }
- 30 }
测试
- 1 [TestClass]
- 2 public class StateMachineTest
- 3 {
- 4 [TestMethod]
- 5 public void ValidSave()
- 6 {
- 7 var order = new Order { Status = Status.UnSaved };
- 8 order.Save();
- 9
- 10 Assert.AreEqual(Status.Saved, order.Status);
- 11 }
- 12
- 13 [TestMethod]
- 14 [ExpectedException(typeof(StateScheduleException))]
- 15 public void InvalidSubmit()
- 16 {
- 17 var order = new Order { Status = Status.UnSaved };
- 18 order.Submit();
- 19 }
- 20 }
一个相对完善的例子返回目录
代码
- 1 using System;
- 2 using System.Collections.Generic;
- 3 using System.Collections.ObjectModel;
- 4 using System.Linq;
- 5 using System.Text;
- 6 using System.Threading.Tasks;
- 7
- 8 using Happy.Domain;
- 9 using Happy.StateManager;
- 10
- 11 namespace Happy.Examples.ManufactureManagement.Domain.Bases
- 12 {
- 13 public abstract class MIAggregateRoot<TItem> : AggregateRoot<Guid>
- 14 {
- 15 protected MIAggregateRoot()
- 16 {
- 17 this.StateMache =
- 18 StateMachine<Status, Operation>
- 19 .Config(() => this.Status, status => this.Status = status)
- 20 .In(Status.UnSaved).When(Operation.Save).If(CanSave).TransferTo(Status.Saved)
- 21 .In(Status.UnSaved).When(Operation.Edit).Aways().Ok()
- 22 .In(Status.Saved).When(Operation.Submit).If(this.CanSubmit).TransferTo(Status.Submitted)
- 23 .In(Status.Saved).When(Operation.Edit).Aways().Ok()
- 24 .In(Status.Submitted).When(Operation.Verify).If(this.CanVerify).TransferTo(Status.Verified)
- 25 .Done();
- 26
- 27 // ReSharper disable DoNotCallOverridableMethodsInConstructor
- 28 this.Items = new Collection<TItem>();
- 29 // ReSharper restore DoNotCallOverridableMethodsInConstructor
- 30 }
- 31
- 32 protected StateMachine<Status, Operation> StateMache { get; private set; }
- 33
- 34 protected internal virtual ICollection<TItem> Items { get; protected set; }
- 35
- 36 internal Status Status { get; set; }
- 37
- 38 protected virtual bool CanSave()
- 39 {
- 40 return true;
- 41 }
- 42
- 43 protected virtual bool CanSubmit()
- 44 {
- 45 return true;
- 46 }
- 47
- 48 protected virtual bool CanVerify()
- 49 {
- 50 return true;
- 51 }
- 52
- 53 internal void Save()
- 54 {
- 55 this.StateMache.Schedule(Operation.Save);
- 56 }
- 57
- 58 internal void Submit()
- 59 {
- 60 this.StateMache.Schedule(Operation.Submit);
- 61 }
- 62
- 63 internal void Verify()
- 64 {
- 65 this.StateMache.Schedule(Operation.Verify);
- 66 }
- 67
- 68 internal void AddItem(TItem item)
- 69 {
- 70 this.AddItems(new List<TItem> { item });
- 71 }
- 72
- 73 internal void AddItems(IEnumerable<TItem> items)
- 74 {
- 75 this.StateMache.Schedule(Operation.Edit);
- 76
- 77 foreach (var item in items)
- 78 {
- 79 this.Items.Add(item);
- 80 }
- 81 }
- 82
- 83 internal void DeleteItem(TItem item)
- 84 {
- 85 this.DeleteItems(new List<TItem> { item });
- 86 }
- 87
- 88 internal void DeleteItems(IEnumerable<TItem> items)
- 89 {
- 90 this.StateMache.Schedule(Operation.Edit);
- 91
- 92 foreach (var item in items)
- 93 {
- 94 this.Items.Remove(item);
- 95 }
- 96 }
- 97 }
- 98 }
测试
- 1 using System;
- 2 using Microsoft.VisualStudio.TestTools.UnitTesting;
- 3
- 4 using Happy.StateManager;
- 5 using Happy.Examples.ManufactureManagement.Domain.Bases;
- 6 using Happy.Examples.ManufactureManagement.Domain.QualityTests;
- 7
- 8 namespace Happy.Examples.ManufactureManagement.Domain.Test.QualityTests
- 9 {
- 10 [TestClass]
- 11 public class QualityTestTest
- 12 {
- 13 [TestMethod]
- 14 public void TestUnSavedQualityTest()
- 15 {
- 16 var entity = this.MockUnQualityTest(Status.UnSaved);
- 17 entity.AddItem(new QualityTestItem(Guid.NewGuid(), entity.Id));
- 18 entity.Save();
- 19
- 20 Assert.AreEqual(Status.Saved, entity.Status);
- 21 }
- 22
- 23 [TestMethod]
- 24 public void TestSavedQualityTest()
- 25 {
- 26 var entity = this.MockUnQualityTest(Status.Saved);
- 27 entity.AddItem(new QualityTestItem(Guid.NewGuid(), entity.Id));
- 28 entity.Submit();
- 29
- 30 Assert.AreEqual(Status.Submitted, entity.Status);
- 31 }
- 32
- 33 [TestMethod]
- 34 [ExpectedException(typeof(StateScheduleException))]
- 35 public void TestSubmittedQualityTest()
- 36 {
- 37 var entity = this.MockUnQualityTest(Status.Submitted);
- 38 entity.AddItem(new QualityTestItem(Guid.NewGuid(), entity.Id));
- 39 }
- 40
- 41 private QualityTest MockUnQualityTest(Status status)
- 42 {
- 43 return new QualityTest
- 44 {
- 45 Id = Guid.NewGuid(),
- 46 Status = status
- 47 };
- 48 }
- 49 }
- 50 }
实现代码返回目录
代码
- 1 using System;
- 2 using System.Collections.Generic;
- 3 using System.Linq;
- 4 using System.Text;
- 5 using System.Threading.Tasks;
- 6
- 7 using Happy.ExtentionMethods;
- 8 using Happy.StateManager.Configuration;
- 9
- 10 namespace Happy.StateManager
- 11 {
- 12 /// <summary>
- 13 /// 状态机。
- 14 /// </summary>
- 15 public sealed class StateMachine<TState, TOperation>
- 16 {
- 17 private readonly List<Transition<TState, TOperation>> _transitions = new List<Transition<TState, TOperation>>();
- 18 private readonly Func<TState> _stateGetter;
- 19 private readonly Action<TState> _stateSetter;
- 20
- 21 /// <summary>
- 22 /// 构造方法。
- 23 /// </summary>
- 24 public StateMachine(Func<TState> stateGetter, Action<TState> stateSetter)
- 25 {
- 26 stateGetter.MustNotNull("stateGetter");
- 27 stateSetter.MustNotNull("stateSetter");
- 28
- 29 _stateGetter = stateGetter;
- 30 _stateSetter = stateSetter;
- 31 }
- 32
- 33 /// <summary>
- 34 /// 配置状态机。
- 35 /// </summary>
- 36 public static IConfig<TState, TOperation> Config(Func<TState> stateGetter, Action<TState> stateSetter)
- 37 {
- 38 stateGetter.MustNotNull("stateGetter");
- 39 stateSetter.MustNotNull("stateSetter");
- 40
- 41 return new Config<TState, TOperation>(stateGetter, stateSetter);
- 42 }
- 43
- 44 /// <summary>
- 45 /// 配置状态迁移。
- 46 /// </summary>
- 47 public StateMachine<TState, TOperation> ConfigTransition(
- 48 TState sourceState,
- 49 TOperation operation,
- 50 ICondition condition,
- 51 TState targetState)
- 52 {
- 53 sourceState.MustNotNull("sourceState");
- 54 operation.MustNotNull("operation");
- 55 condition.MustNotNull("condition");
- 56 targetState.MustNotNull("targetState");
- 57
- 58 var transition = new Transition<TState, TOperation>(
- 59 sourceState,
- 60 operation,
- 61 condition,
- 62 targetState);
- 63
- 64 _transitions.Add(transition);
- 65
- 66 return this;
- 67 }
- 68
- 69 /// <summary>
- 70 /// 使用<paramref name="operation"/>调度状态机。
- 71 /// </summary>
- 72 public void Schedule(TOperation operation)
- 73 {
- 74 operation.MustNotNull("operation");
- 75
- 76 var currentState = _stateGetter();
- 77 var transition = _transitions
- 78 .FirstOrDefault(x =>
- 79 x.SourceState.Equals(currentState)
- 80 &&
- 81 x.Operation.Equals(operation)
- 82 &&
- 83 x.Condition.IsSatisfied());
- 84
- 85 if (transition == null)
- 86 {
- 87 throw new StateScheduleException(currentState, operation);
- 88 }
- 89
- 90 _stateSetter(transition.TargetState);
- 91 }
- 92 }
- 93 }
说明
内部就是一个状态表格,没啥交代的,有兴趣的朋友可以去 http://happy.codeplex.com/SourceControl/latest,找到 Happyframework/Src/Happy.StateManager 下载最新代码看看。
进一步交代的问题返回目录
如果需要在真实的项目中使用这个模式,有两个问题还需要解决:
第一个问题:迁移的前置条件判断和后置操作的执行如果需要更多的信息,而这些信息不在实体内,怎么办?处理这个问题有很多种方式,这里介绍一下我目前最偏好的一种,引入领域服务:
领域服务代码
- 1 using System;
- 2 using System.Collections.Generic;
- 3 using System.Linq;
- 4 using System.Text;
- 5 using System.Threading.Tasks;
- 6
- 7 using Happy.Examples.ManufactureManagement.Domain.QualityTests;
- 8 using Happy.Examples.ManufactureManagement.Domain.SmallCuts;
- 9
- 10 namespace Happy.Examples.ManufactureManagement.Domain.Services
- 11 {
- 12 public sealed class QualityTestManager
- 13 {
- 14 private readonly ISmallCutRepository _smallCutRepository;
- 15
- 16 public QualityTestManager(ISmallCutRepository smallCutRepository)
- 17 {
- 18 _smallCutRepository = smallCutRepository;
- 19 }
- 20
- 21 public void Save(
- 22 QualityTest qualityTest,
- 23 IEnumerable<QualityTestItem> addedItems,
- 24 IEnumerable<QualityTestItem> deletedItems)
- 25 {
- 26 qualityTest.AddItems(addedItems);
- 27 qualityTest.DeleteItems(deletedItems);
- 28
- 29 qualityTest.Save();
- 30
- 31 this.AcquireLocks(qualityTest, addedItems);
- 32 this.ReleaseLocks(qualityTest, deletedItems);
- 33 }
- 34
- 35 public void Submit(
- 36 QualityTest qualityTest,
- 37 IEnumerable<QualityTestItem> addedItems,
- 38 IEnumerable<QualityTestItem> deletedItems)
- 39 {
- 40 qualityTest.AddItems(addedItems);
- 41 qualityTest.DeleteItems(deletedItems);
- 42
- 43 qualityTest.Submit();
- 44
- 45 this.AcquireLocks(qualityTest, addedItems);
- 46 this.ReleaseLocks(qualityTest, deletedItems);
- 47 }
- 48
- 49 public void Verify(QualityTest qualityTest)
- 50 {
- 51 qualityTest.Verify();
- 52
- 53 foreach (var item in qualityTest.Items)
- 54 {
- 55 var smallCut = _smallCutRepository.Load(item.SmallCutId);
- 56 smallCut.ReleaseLock(CreateLockInfo(qualityTest));
- 57 }
- 58 }
- 59
- 60 private void AcquireLocks(QualityTest qualityTest, IEnumerable<QualityTestItem> addedItems)
- 61 {
- 62 foreach (var item in addedItems)
- 63 {
- 64 var smallCut = _smallCutRepository.Load(item.SmallCutId);
- 65 smallCut.AcquireLock(CreateLockInfo(qualityTest));
- 66 }
- 67 }
- 68
- 69 private void ReleaseLocks(QualityTest qualityTest, IEnumerable<QualityTestItem> deletedItems)
- 70 {
- 71 foreach (var item in deletedItems)
- 72 {
- 73 var smallCut = _smallCutRepository.Load(item.SmallCutId);
- 74 smallCut.ReleaseLock(CreateLockInfo(qualityTest));
- 75 }
- 76 }
- 77
- 78 private static LockInfo CreateLockInfo(QualityTest qualityTest)
- 79 {
- 80 return new LockInfo(LockType.LockByQualityTest, qualityTest.Id);
- 81 }
- 82 }
- 83 }
第二个问题:之前我只需要在 UI 中控制好这种状态机就行了,如果移动到了领域层,UI 也要重复一遍了,如何消除这种重复,答案是:引入元编程,让 UI 能自动识别这些元数据,最小化重复,这里就不给出实现(还没做)。
备注返回目录
上面状态机的配置过程也很有意思,In后只能是When,When后可以是If或Always,有点类似语法树了,找个机会可以写篇文章(实现是很简单的)。
集群管理工具Salt的更多相关文章
- 译:Google的大规模集群管理工具Borg(一)------ 用户视角的Borg特性
概述 Google的Borg系统是一个集群管理工具,在它上面运行着成千上万的job,这些job来自许许多多不同的应用,并且跨越多个集群,而每个集群又由大量的机器构成. Borg通过组合准入控制,高效的 ...
- elasticsearch集群管理工具head插件(转)
elasticsearch-head是一个elasticsearch的集群管理工具,它是完全由html5编写的独立网页程序,你可以通过插件把它集成到es 插件安装方法1: 1.elasticsearc ...
- Redis核心解读:集群管理工具(Redis-sentinel)
Redis核心解读:集群管理工具(Redis-sentinel) - Redis - TechTarget数据库 Redis核心解读:集群管理工具(Redis-sentinel)
- 大规模集群管理工具Borg
Google的大规模集群管理工具Borg 概述 Google的Borg系统是一个集群管理工具,在它上面运行着成千上万的job,这些job来自许许多多不同的应用,并且跨越多个集群,而每个集群又由大量的机 ...
- Kafka集群管理工具kafka-manager的安装使用
一.kafka-manager简介 kafka-manager是目前最受欢迎的kafka集群管理工具,最早由雅虎开源,用户可以在Web界面执行一些简单的集群管理操作.具体支持以下内容: 管理多个集群 ...
- Linux Kafka集群管理工具kafka-manager的安装使用
一.kafka-manager简介 kafka-manager是目前最受欢迎的kafka集群管理工具,最早由雅虎开源,用户可以在Web界面执行一些简单的集群管理操作.具体支持以下内容: 管理多个集群 ...
- Elasticsearch集群管理工具head插件安装
Elasticsearch-head是一个elasticsearch的集群管理工具,它是完全由html5编写的独立网页程序,你可以通过插件把它集成到es.或直接下载源码,在本地打开index.html ...
- 安装memcache集群管理工具
安装memcache集群管理工具magent 一.安装libevent tar xf libevent--stable.tar.gz cd libevent- ./configure --prefix ...
- Kafka设计解析(十七)Kafka 0.11客户端集群管理工具AdminClient
转载自 huxihx,原文链接 Kafka 0.11客户端集群管理工具AdminClient 很多用户都有直接使用程序API操作Kafka集群的需求.在0.11版本之前,kafka的服务器端代码(即添 ...
随机推荐
- FFmpeg 协议初步学习
typedef struct URLContext { const AVClass *av_class; /**< information for av_log(). Set by url_op ...
- Hadoop之——CentOS构造ssh否password登录注意事项
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46388809 前提配置:使用root登录改动配置文件:/etc/ssh/sshd_ ...
- Codeforces Round #248 (Div. 2) (ABCD解决问题的方法)
比赛链接:http://codeforces.com/contest/433 A. Kitahara Haruki's Gift time limit per test:1 second memory ...
- c/cpp中怎样切割字符串,相似于split的功能
在python中,假设要求当前时间的unix时间戳,我特别喜欢这么用: import time timestr = time.time() timestamp = int(timestr.split( ...
- vim插件管理器vundle
安装: git clone http://github.com/gmarik/vundle.git ~/.vim/bundle/vundle set nocompatible " be i ...
- session什么时候被创建
一个常见的错误是以为 session 在有客户端访问时就被创建,然而事实是直到某 server 端程序(如 Servlet )调用HttpServletRequest.getSession(true) ...
- 使用oracle的exp命令时,提示出--hash: exp: command not found
使用oracle的exp命令时,提示出--hash: exp: command not found 原因:当你在终端使用exp的命名时,当前的账户,并不是oracle认可的账户. 在安装oracle时 ...
- AutoCAD 2012安装错误,与.net framework (1603错误)以及ms2005vc++的问题。
首先,这是AutoCAD2012的问题.因为,如果一台计算机已经安装了这些软件,AutoCAD是无法识别出来,因此AutoCAD就只能报错.正确的做法是:如果检测到这些软件已经被安装,则需要忽略这些问 ...
- 大endian和little endian
大endian和little endian 一般Intel处理器或X86平台是小端 ,只是有点老了摩托罗拉的处理器将采用大端,掌握一下小端序. 小端序一般指低地址存低字节.高地址存高 ...
- Java多线程之进程和线程
在并发编程中有两个基本的概率就是进程和线程.在Java编程中并发编程更多的是关注线程.但是进程也是很重要的. 一个计算机一般会有很多活跃的进程和线程.有一点是没有疑问的在单核系统中,任何时候实际上都是 ...