Linux PID 1 和 Systemd

systemd 是 Linux 下的一款系统和服务管理器,兼容 SysV 和 LSB 的启动脚本。systemd 的特性有:支持并行化任务;同时采用 socket 式与 D-Bus 总线式激活服务;按需启动守护进程(daemon);利用 Linux 的 cgroups 监视进程;支持快照和系统恢复;维护挂载点和自动挂载点;各服务间基于依赖关系进行精密控制。

要说清 Systemd,得先从Linux操作系统的启动说起。Linux 操作系统的启动首先从 BIOS 开始,然后由 Boot Loader 载入内核,并初始化内核。内核初始化的最后一步就是启动 init 进程。这个进程是系统的第一个进程,PID 为 1,又叫超级进程,也叫根进程。它负责产生其他所有用户进程。所有的进程都会被挂在这个进程下,如果这个进程退出了,那么所有的进程都被 kill 。如果一个子进程的父进程退了,那么这个子进程会被挂到 PID 1 下面。(注:PID 0 是内核的一部分,主要用于内进换页,参看:Process identifier

SysV Init

PID 1 这个进程非常特殊,其主要就任务是把整个操作系统带入可操作的状态。比如:启动 UI – Shell 以便进行人机交互,或者进入 X 图形窗口。传统上,PID 1 和传统的 Unix System V 相兼容的,所以也叫 sysvinit,这是使用得最悠久的 init 实现。Unix System V 于1983年 release。

在 sysvint 下,有好几个运行模式,又叫 runlevel。比如:常见的 3 级别指定启动到多用户的字符命令行界面,5 级别指定启起到图形界面,0 表示关机,6 表示重启。其配置在 /etc/inittab 文件中。

与此配套的还有 /etc/init.d/ 和 /etc/rc[X].d,前者存放各种进程的启停脚本(需要按照规范支持 startstop子命令),后者的 X 表示不同的 runlevel 下相应的后台进程服务,如:/etc/rc3.d 是 runlevel=3 的。 里面的文件主要是 link 到  /etc/init.d/ 里的启停脚本。其中也有一定的命名规范:S 或 K 打头的,后面跟一个数字,然后再跟一个自定义的名字,如:S01rsyslogS02ssh。S 表示启动,K表示停止,数字表示执行的顺序。

UpStart

Unix 和 Linux 在 sysvint 运作多年后,大约到了2006年的时候,Linux内核进入2.6时代,Linux有了很多更新。并且,Linux开始进入桌面系统,而桌面系统和服务器系统不一样的是,桌面系统面临频繁重启,而且,用户会非常频繁的使用硬件的热插拔技术。于是,这些新的场景,让 sysvint 受到了很多挑战。

比如,打印机需要CUPS等服务进程,但是如果用户没有打机印,启动这个服务完全是一种浪费,而如果不启动,如果要用打印机了,就无法使用,因为sysvint 没有自动检测的机制,它只能一次性启动所有的服务。另外,还有网络盘挂载的问题。在 /etc/fstab中,负责硬盘挂载,有时候还有网络硬盘(NFS 或 iSCSI)在其中,但是在桌面机上,有很可能开机的时候是没有网络的, 于是网络硬盘都不可以访问,也无法挂载,这会极大的影响启动速度。sysvinit 采用 netdev 的方式来解决这个问题,也就是说,需要用户自己在 /etc/fstab 中给相应的硬盘配置上 netdev 属性,于是 sysvint 启动时不会挂载它,只有在网络可用后,由专门的 netfs 服务进程来挂载。这种管理方式比较难以管理,也很容易让人掉坑。

所以,Ubuntu 开发人员在评估了当时几个可选的 init 系统后,决定重新设计这个系统,于是,这就是我们后面看到的 upstart 。 upstart 基于事件驱动的机制,把之前的完全串行的同步启动服务的方式改成了由事件驱动的异步的方式。比如:如果有U盘插入,udev得到通知,upstart 感知到这个事件后触发相应的服务程序,比如挂载文件系统等等。因为使用一个事件驱动的玩法,所以,启动操作系统时,很多不必要的服务可以不用启动,而是等待通知,lazy 启动。而且事件驱动的好处是,可以并行启动服务,他们之间的依赖关系,由相应的事件通知完成。

upstart 有着很不错的设计,其中最重要的两个概念是 Job 和 Event。

Job 有一般的Job,也有service的Job,并且,upstart 管理了整个 Job 的生命周期,比如:Waiting, Starting, pre-Start, Spawned, post-Start, Running, pre-Stop, Stopping, Killed, post-Stop等等,并维护着这个生命周期的状态机。

Event 分成三类,signalmethod 和 hookssignal 就是异步消息,method 是同步阻塞的。hooks 也是同步的,但介于前面两者之间,发出hook事件的进程必须等到事件完成,但不检查是否成功。

但是,upstart 的事件非常复杂,也非常纷乱,各种各样的事件(事件没有归好类)导致有点凌乱。不过因为整个事件驱动的设计比之前的 sysvinit 来说好太多,所以,也深得欢迎。

Systemd

直到2010的有一天,一个在 RedHat工作的工程师 Lennart Poettering 和 Kay Sievers ,开始引入了一个新的 init 系统—— systemd。这是一个非常非常有野心的项目,这个项目几乎改变了所有的东西,systemd 不但想取代已有的 init 系统,而且还想干更多的东西。

Lennart 同意 upstart 干的不错,代码质量很好,基于事件的设计也很好。但是他觉得 upstart 也有问题,其中最大的问题还是不够快,虽然 upstart 用事件可以达到一定的启动并行度,但是,本质上来说,这些事件还是会让启动过程串行在一起。  如:NetworkManager 在等 D-Bus 的启动事件,而 D-Bus 在等 syslog 的启动事件。

Lennart 认为,实现上来说,upstart 其实是在管理一个逻辑上的服务依赖树,但是这个服务依赖树在表现形式上比较简单,你只需要配置——“启动 B好了就启动A”或是“停止了A后就停止B”这样的规则。但是,Lennart 说,这种简单其实是有害的(this simplification is actually detrimental)。他认为,

  • 从一个系统管理的角度出来,他一开始会设定好整个系统启动的服务依赖树,但是这个系统管理员要人肉的把这个本来就非常干净的服务依整树给翻译成计算机看的懂的 Event/Action 形式,而且 Event/Action 这种配置方式是运行时的,所以,你需要运行起来才知道是什么样的。
  • Event逻辑从头到脚到处都是,这个事件扩大了运维的复杂度,还不如之前的 sysvint。 也就是说,当用户配置了 “启动 D-Bus 后请启动 NetworkManager”, 这个 upstart 可以干,但是反过来,如果,用户启动 NetworkManager,我们应该先去启动他的前置依赖 D-Bus,然而你还要配置相应的反向 Event。本来,我只需要配置一条依赖的,结果现在我要配置很多很多情况下的Event。
  • 最后,upstart 里的 Event 的并不标准,很混乱,没有良好的定义。比如:既有,进程启动,运行,停止的事件,也有USB设备插入、可用、拔出的事件,还有文件系统设备being mounted、 mounted 和 umounted 的事件,还有AC电源线连接和断开的事件。你会发现,这进程启停的、USB的、文件系统的、电源线的事件,看上去长得很像, 但是没有被标准化抽像出来掉,因为绝大多数的事件都是三元组:start, condition, stop 。这种概念设计模型并没有在 upstart 中出现。因为 upstart 被设计为单一的事件,而忽略了逻辑依赖。

当然,如果 systemd 只是解决 upstart 的问题,他就改造 upstart 就好了,但是 Lennart 的野心不只是想干个这样的事,他想干的更多。

首先,systemd 清醒的认识到了 init 进程的首要目标是要让用户快速的进入可以操作OS的环境,所以,这个速度一定要快,越快越好,所以,systemd 的设计理念就是两条:

  • To start less.
  • And to start more in parallel.

也就是说,按需启动,能不启动就不启动,如果要启动,能并行启动就并行启动,包括你们之间有依赖,我也并行启动。按需启动还好理解,那么,有依赖关系的并行启动,它是怎么做到的?这里,systemd 借鉴了 MacOS 的 Launchd 的玩法(在Youtube上有一个分享——Launchd: One Program to Rule them All,在苹果的开源网站上也有相关的设计文档——About Daemons and Services

要解决这些依赖性,systemd 需要解决好三种底层依赖—— Socket, D-Bus ,文件系统。

  • Socket依赖。如果服务C依赖于服务S的socket,那么就要先启动S,然后再启动C,因为如果C启动时找不到S的Socket,那么C就会失败。systemd 可以帮你在S还没有启动好的时候,建立一个socket,用来接收所有的C的请求和数据,并缓存之,一旦S全部启动完成,把systemd替换好的这个缓存的数据和Socket描述符替换过去。
  • D-Bus依赖D-Bus 全称 Desktop Bus,是一个用来在进程间通信的服务。除了用于用户态进程和内核态进程通信,也用于用户态的进程之前。现在,很多的现在的服务进程都用 D-Bus 而不是Socket来通信。比如:NetworkManager 就是通过 D-Bus 和其它服务进程通讯的,也就是说,如果一个进程需要知道网络的状态,那么就必需要通过 D-Bus 通信。D-Bus 支持 “Bus Activation”的特性。也就是说,A要通过 D-Bus服务和B通讯,但是B没有启动,那么 D-Bus 可以把B起来,在B启动的过程中,D-Bus 帮你缓存数据。systemd 可以帮你利用好这个特性来并行启动 A 和 B。
  • 文件系统依赖。系统启动过程中,文件系统相关的活动是最耗时的,比如挂载文件系统,对文件系统进行磁盘检查(fsck),磁盘配额检查等都是非常耗时的操作。在等待这些工作完成的同时,系统处于空闲状态。那些想使用文件系统的服务似乎必须等待文件系统初始化完成才可以启动。systemd 参考了 autofs 的设计思路,使得依赖文件系统的服务和文件系统本身初始化两者可以并发工作。autofs 可以监测到某个文件系统挂载点真正被访问到的时候才触发挂载操作,这是通过内核 automounter 模块的支持而实现的。比如一个 open() 系统调用作用在某个文件系统上的时候,而这个文件系统尚未执行挂载,此时 open() 调用被内核挂起等待,等到挂载完成后,控制权返回给 open() 系统调用,并正常打开文件。这个过程和 autofs 是相似的。

下图来自 Lennart 的演讲里的一页PPT,展示了不同 init 系统的启动。

启动流程

除此之外,systemd 还在启动时管理好了一些下面的事。

用C语言取代传统的脚本式的启动。前面说过,sysvint 用 /etc/rcX.d 下的各种脚本启动。然而这些脚本中需要使用 awksedgrepfindxargs 等等这些操作系统的命令,这些命令需要生成进程,生成进程的开销很大,关键是生成完这些进程后,这个进程就干了点屁大的事就退了。换句话说就是,我操作系统干了那么多事为你拉个进程起来,结果你就把个字串转成小写就退了,把我操作系统当什么了?

在正常的一个 sysvinit 的脚本里,可能会有成百上千个这样的命令。所以,慢死。因此,systemd 全面用 C 语言全部取代了。一般来说,sysvinit 下,操作系统启动完成后,用 echo $$ 可以看到,pid 被分配到了上千的样子,而 systemd 的系统只是上百。

另外,systemd 是真正一个可以管住服务进程的——可以跟踪上服务进程所fork/exec出来的所有进程。

  • 我们知道, 传统 Unix/Linux 的 Daemon 服务进程的最佳实践基本上是这个样子的 (具体过程可参看这篇文章“SysV Daemon”)——
    1. 进程启动时,关闭所有的打开的文件描述符(除了标准描述符0,1,2),然后重置所有的信号处理。
    2. 调用 fork() 创建子进程,在子进程中 setsid(),然后父进程退出(为了后台执行)
    3. 在子进程中,再调用一次 fork(),创建孙子进程,确定没有交互终端。然后子进程退出。
    4. 在孙子进程中,把标准输入标准输出标准错误都连到 /dev/null 上,还要创建 pid 文件,日志文件,处理相关信号 ……
    5. 最后才是真正开始提供服务。
  • 在上面的这个过程中,服务进程除了两次 fork 外还会 fork 出很多很多的子进程(比如说一些Web服务进程,会根据用户的请求链接来 fork 子进程),这个进程树是相当难以管理的,因为,一旦父进程退出来了,子进程就会被挂到 PID 1下,所以,基本上来说,你无法通过服务进程自已给定的一个pid文件来找到所有的相关进程(这个对开发者的要求太高了),所以,在传统的方式下用脚本启停服务是相当相当的 Buggy 的,因为无法做对所有的服务生出来的子子孙孙做到监控。
  • 为了解决这个问题,upstart 通过变态的 strace 来跟踪进程中的 fork() 和 exec()或 exit() 等相关的系统调用。这种方法相当笨拙。 systemd 使用了一个非常有意思的玩法来 tracking 服务进程生出来的所有进程,那就是用 cgroup (我在 Docker 的基础技术“cgroup篇”中讲过这个东西)。cgroup主要是用来管理进程组资源配额的事,所以,无论服务如何启动新的子进程,所有的这些相关进程都会同属于一个 cgroup,所以,systemd 只需要简单的去遍历一下相应的 cgroup 的那个虚文件系统目录下的文件,就可以正确的找到所有的相关进程,并将他们一一停止。

另外,systemd 简化了整个 daemon 开发的过程:

  • 不需要两次 fork(),只需要实现服务本身的主逻辑就可以了。
  • 不需要 setsid()systemd 会帮你干
  • 不需要维护 pid文件systemd 会帮处理。
  • 不需要管理日志文件或是使用syslog,或是处理HUP的日志reload信号。把日志打到 stderr 上,systemd 帮你管理。
  • 处理 SIGTERM 信号,这个信号就是正确退出当前服务,不要做其他的事。
  • ……

除此之外,systemd 还能——

  • 自动检测启动的服务间有没有环形依赖。
  • 内建 autofs 自动挂载管理功能。
  • 日志服务。systemd 改造了传统的 syslog 的问题,采用二进制格式保存日志,日志索引更快。
  • 快照和恢复。对当前的系统运行的服务集合做快照,并可以恢复。
  • ……

还有好多好多,他接管很多很多东西,于是就让很多人不爽了,因为他在干了很多本不属于 PID 1 的事。

Systemd 争论和八卦

于是 systemd 这个东西成了可能是有史以来口水战最多的一个开源软件了。systemd 饱受各种争议,最大的争议就是他破坏了 Unix 的设计哲学(相关的哲学可以读一下《Unix编程艺术》),干了一个大而全而且相当复杂的东西。当然,Lennart 并不同意这样的说法,他后来又写一篇blog “The Biggest Myths”来解释 systemd 并不是这样的,大家可以前往一读。

这个争议大到什么样子呢?2014 年,Debian Linux 因为想准备使用 systemd 来作为标准的 init 守护进程来替换 sysvinit 。而围绕这个事的争论达到了空前的热度,争论中充满着仇恨,systemd 的支持者和反对者都在互相辱骂,导致当时 Debian 阵营开始分裂。还有人给 Lennart 发了死亡威胁的邮件,用比特币雇凶买杀手,扬言要取他的性命,在Youbute上传了侮辱他的歌曲,在IRC和各种社交渠道上给他发下流和侮辱性的消息。这已经不是争议了,而是一种不折不扣的仇恨!

systemd shewantsit

于是,Lennart 在 Google Plus 上发了贴子,批评整个 Linux 开源社区和 Linus 本人。他大意说,

这个社区太病态了,全是 ass holes,你们不停用各种手段在各种地方用不同的语言和方式来侮辱和漫骂我。我还是一个年轻人,我从来没有经历过这样的场面,但是今天我已经对这种场面很熟悉了。我有时候说话可能不准确,但是我不会像他样那样说出那样的话,我也没有被这些事影响,因为我脸皮够厚,所以,为什么我可以在如何大的反对声面前让 systemd 成功,但是,你们 Linux 社区太可怕了。你们里面的有精神病的人太多了。另外,对于Linus Torvalds,你是这个社区的 Role Model,但可惜你是一个 Bad Role Model,你在社区里的刻薄和侮辱性的言行,基本从一定程度上鼓励了其它人跟你一样,当然,并不只是你一个人的问题,而是在你周围聚集了一群和你一样的这样干的人。送你一句话—— A fish rots from the head down !一条鱼是从头往下腐烂的……

这篇契文很长,喜欢八卦的同学可以前往一读。感受一下 Lennart 当时的心态(我觉得能算上是非常平稳了)。

Linus也在被一媒体问起 systemd 这个事来(参看“Torvalds says he has no strong opinions on systemd”),Linus在采访里说,

我对 systemd 和 Lennart 的贴子没有什么强烈的想法。虽然,传统的 Unix 设计哲学—— “Do one thing and Do it well”,很不错,而且我们大多数人也实践了这么多年,但是这并不代表所有的真实世界。在历史上,也不只有systemd 这么干过。但是,我个人还是 old-fashioned 的人,至少我喜欢文本式的日志,而不是二进制的日志。但是 systemd 没有必要一定要有这样的品味。哦,我说细节了……

今天,systemd 占据了几乎所有的主流的 Linux 发行版的默认配置,包括:Arch Linux、CentOS、CoreOS、Debian、Fedora、Megeia、OpenSUSE、RHEL、SUSE企业版和 Ubuntu。而且,对于 CentOS, CoreOS, Fedora, RHEL, SUSE这些发行版来说,不能没有 systemd。(Ubuntu 还有一个不错的wiki – Systemd for Upstart Users 阐述了如何在两者间切换)

其它

还记得在《缓存更新的套路》一文中,我说过,如果你要做好架构,首先你得把计算机体系结构以及很多老古董的基础技术吃透了。因为里面会有很多可以借鉴和相通的东西。那么,你是否从这篇文章里看到了一些有分布式架构相似的东西?

比如:从 sysvinit 到 upstart 再到 systemd,像不像是服务治理?Linux系统下的这些服务进程,是不是很像分布式架构中的微服务?还有那个D-Bus,是不是很像SOA里的ESB?而 init 系统是不是很像一个控制系统?甚至像一个服务编排(Service Orchestration)系统?

分布式系统中的服务之间也有很多依赖,所以,在启动一个架构的时候,如果我们可以做到像 systemd 那样并行启动的话,那么是不是就像是一个微服务的玩法了?

嗯,你会发现,技术上的很多东西是相通的,也是互相有对方的影子,所以,其实技术并不多。关键是我们学在了表面还是看到了本质。

延伸阅读

 

转载自: Linux PID 1 和 Systemd | | 酷 壳 – CoolShell

fedora 26 于7月13日正式发布

包括Workstation、Server和Atomic Host版本在内,Fedora 26系统镜像已经正式发布上线。用户可以通过命令行或者GNOME Software非常方面的进行升级,整个升级过程大约需要半个小时。继续为程序员和终端用户提供优质服务,Fedora于今天推出了全新升级的开发者软件,其中包括GCC 7,Golang 1.8和Python 3.6等等。

Fedora 26

包括Workstation、Server和Atomic Host版本在内,Fedora 26系统镜像已经正式发布上线。用户可以通过命令行或者GNOME Software非常方面的进行升级,整个升级过程大约需要半个小时。继续为程序员和终端用户提供优质服务,Fedora于今天推出了全新升级的开发者软件,其中包括GCC 7,Golang 1.8和Python 3.6等等。

此外在Fedora安装器中引入了全新的分区工具Anaconda,能够赋予系统爱好者和系统管理员更精细的控制选项。此外在本次升级中对Fedora 26的后台性能进行了诸多优化,例如更好的缓存用户和群组信息,更好的处理调试信息等等。此外在2.5重大版本更新中DNF安装包管理器也新增了很多功能。

下载地址:

Stack Clash提权漏洞曝光

2017年6月19日Unix操作系统(包括Linux、OpenBSD和FreeBSD)爆出存在提权漏洞,该漏洞让攻击者可以通过执行代码提权到root权限。这个问题最早由安全供应商Qualys发现,并根据该漏洞需要和其他的内存区的堆栈进行“碰撞冲突”特性,将其命名为“Stack Clash”(堆栈冲突)。

StackClash

2017年6月19日Unix操作系统(包括Linux、OpenBSD和FreeBSD)爆出存在提权漏洞,该漏洞让攻击者可以通过执行代码提权到root权限。这个问题最早由安全供应商Qualys发现,并根据该漏洞需要和其他的内存区的堆栈进行“碰撞冲突”特性,将其命名为“Stack Clash”(堆栈冲突)。

具体详情如下:

漏洞编号:CVE-2017-1000364

CVE-2017-1000366

漏洞名称:Linux Kernel Stack Clash安全漏洞

官方评级:高危

漏洞描述:该漏洞是由于操作系统内存管理中的一个堆栈冲突漏洞,它影响的Linux,FreeBSD,OpenBSD,NetBSD的,Solaris和I386和AMD64,攻击者可以利用它破坏内存并执行任意代码。

漏洞利用条件和方式:可以直接远程利用

受到影响的 Linux 发行版

  • Red Hat Enterprise Linux Server 5.x
  • Red Hat Enterprise Linux Server 6.x
  • Red Hat Enterprise Linux Server 7.x
  • CentOS Linux Server 5.x
  • CentOS Linux Server 6.x
  • CentOS Linux Server 7.x
  • Oracle Enterprise Linux Server 5.x
  • Oracle Enterprise Linux Server 6.x
  • Oracle Enterprise Linux Server 7.x
  • Ubuntu 17.10
  • Ubuntu 17.04
  • Ubuntu 16.10
  • Ubuntu 16.04 LTS
  • Ubuntu 12.04 ESM (Precise Pangolin)
  • Debian 9 stretch
  • Debian 8 jessie
  • Debian 7 wheezy
  • Debian unstable
  • SUSE Linux Enterprise Desktop 12 SP2
  • SUSE Linux Enterprise High Availability 12 SP2
  • SUSE Linux Enterprise Live Patching 12
  • SUSE Linux Enterprise Module for Public Cloud 12
  • SUSE Linux Enterprise Build System Kit 12 SP2
  • SUSE Openstack Cloud Magnum Orchestration 7
  • SUSE Linux Enterprise Server 11 SP3-LTSS
  • SUSE Linux Enterprise Server 11 SP4
  • SUSE Linux Enterprise Server 12 SP1-LTSS
  • SUSE Linux Enterprise Server 12 SP2
  • SUSE Linux Enterprise Server for Raspberry Pi 12 SP2

包括Red Hat、Debian、Ubuntu和SUSE等很多Linux发行机构已经修复了这个漏洞。更多更详细信息可以访问:

SUSE
https://www.novell.com/support/kb/doc.php?id=7020973
Red Hat
https://access.redhat.com/security/vulnerabilities/stackguard
Debian
https://www.debian.org/security/2017/dsa-3886
https://www.debian.org/security/2017/dsa-3887
https://www.debian.org/security/2017/dsa-3888
https://www.debian.org/security/2017/dsa-3889
Ubuntu
https://www.ubuntu.com/usn/
OpenBSD
https://ftp.openbsd.org/pub/OpenBSD/patches/6.1/common/008_exec_subr.patch.sig
Oracle Solaris
http://www.oracle.com/technetwork/security-advisory/alert-cve-2017-3629-3757403.html

Docker 国内Mirror镜像推荐

Docker Registry Mirror的原理类似于缓存,如果镜像在Mirror中命中则直接返回给客户端,否则从存放镜像的Registry上拉取并自动缓存在Mirror中。最酷的是,是否使用Mirror对Docker使用者来讲是透明的,也就是说在配置Mirror以后,大家可以仍然输入docker pull ubuntu来拉取Docker Hub镜像,除了速度变快了,和以前没有任何区别。

前言

Docker Registry Mirror的原理类似于缓存,如果镜像在Mirror中命中则直接返回给客户端,否则从存放镜像的Registry上拉取并自动缓存在Mirror中。最酷的是,是否使用Mirror对Docker使用者来讲是透明的,也就是说在配置Mirror以后,大家可以仍然输入docker pull ubuntu来拉取Docker Hub镜像,除了速度变快了,和以前没有任何区别。

了以更便捷的方式对接Docker Hub生态圈,使用Registry Mirror自然成为我的首选。接下来我就和大家一起看看国内有哪些 Mirror镜像。

1、Docker 官方镜像加速

这是Docker官方的中国区镜像加速,该镜像托管于中国大陆,速度有保证。使用方法详见:Docker 官方镜像加速

2、ustc 镜像加速

ustc是老牌的linux镜像服务提供者了,还在遥远的ubuntu 5.04版本的时候就在用。使用方法详见:Docker 镜像使用帮助

3、网易蜂巢镜像加速

目前网易镜像已经比较稳定。使用方法详见:DockerHub镜像加速

在Debian 8.8安装使用zfs文件系统

ZFS文件系统是一个革命性的新文件系统,从根本上改变了在类Unix操作系统上管理文件系统的方式。 ZFS提供了在今天可用的任何其他文件系统中找不到的功能和优点。 ZFS是强大的,可扩展的,易于管理。

引言

ZFS文件系统的英文名称为ZettabyteFileSystem,也叫动态文件系统(DynamicFileSystem),是第一个128位文件系统。最初是由Sun公司为Solaris10操作系统开发的文件系统。作为OpenSolaris开源计划的一部分,ZFS于2005年11月发布,被Sun称为是终极文件系统,经历了10年的活跃开发,而最新的开发将全面开放,并重新命名为OpenZFS。

ZFS优势

  1. ZFS是一种先进的、高度可扩展的文件系统,最初是由Sun Microsystems开发的,现在OpenZFS是项目的一部分。有这么多文件系统可用在Linux上,那自然要问ZFS有什么特别之处。不同于其它文件系统,它不仅是一个文件系统逻辑卷管理器。ZFS使其受欢迎的特性是:
  2.  数据完整性——数据一致性和完整性通过即写即拷和校验技术保证。
  3. 存储空间池——可用存储驱动器一起放入称为zpool的单个池。
  4. 软件RAID ——像发出一个命令一样,建立一个raidz数组。
  5. 内置的卷管理器——ZFS充当卷管理器。
  6. Snapshots、克隆、压缩——这些都是一些ZFS提供的高级功能。

安装ZFS

在这篇文章中,我们将学习在Debian 8.8上安装、设置和使用ZFS文件系统。

根据网站www.zfsonlinux.org的信息 ,ZFS仅支持AMD64和Intel 64位架构(amd64)。 让我们开始安装。

1、更新Debian系统

在Debian8中,zfs软件包已经加入debian backports源

首先我们需要在系统中启用backports源,并更新系统

echo "deb http://ftp.debian.org/debian jessie-backports main contrib" /etc/apt/sources.list.d/backports.list
aptitiude update
apititiude upgrade

2、安装zfs

安装kernel headers

aptitiude install linux-headers-$(uname -r)

安装 zfs-dkms

aptitiude install -t jessie-backports zfs-dkms

如果需要在在根分区使用zfs,你需要安装zfs-initramfs

aptitiude install -t jessie-backports zfs-initramfs

3、创建和配置池

服务器重新启动后,检查zfsonlinux是否安装并运行良好。


# dpkg -l | grep zfs
ii debian-zfs 7~jessie amd64 Native ZFS filesystem metapackage for Debian.
ii libzfs2 0.6.5.2-2 amd64 Native ZFS filesystem library for Linux
ii zfs-dkms 0.6.5.2-2 all Native ZFS filesystem kernel modules for Linux
ii zfsonlinux 6 all archive.zfsonlinux.org trust package
ii zfsutils 0.6.5.2-2 amd64 command-line tools to manage ZFS filesystems

上面的结果显示,linux上的zfs已经安装好了,所以我们可以继续创建第一个池。

我已经为这台服务器添加了五个磁盘,每个磁盘的大小为2GB。 我们可以使用以下命令检查可用磁盘:


# ls /dev/sd*
/dev/sda /dev/sda1 /dev/sda2 /dev/sda5 /dev/sdb /dev/sdc /dev/sdd /dev/sde /dev/sdf /dev/sdg

我们可以看到/ dev / sda直到/ dev / sdg , / dev / sda用于操作系统Debian Linux Jessie 8.1。 我们将使用/ dev / sdb直到/ dev / sdg为ZFS文件系统。

现在我们可以开始创建池,第一个我会告诉你如何创建一个raid0(条带)。


# zpool list
no pools available

# zpool create -f pool0 /dev/sdb
# zpool list
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
pool0 1.98G 64K 1.98G – 0% 0% 1.00x ONLINE –

命令“zpool list”表示我们成功创建了一个raid0 zfs池,池名为pool0 ,大小为2GB。

接下来我们将创建一个raid1(镜像)与其他磁盘。


# zpool create -f pool1 mirror /dev/sdc /dev/sdd
# zpool list
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
pool0 1.98G 64K 1.98G – 0% 0% 1.00x ONLINE –
pool1 1.98G 64K 1.98G – 0% 0% 1.00x ONLINE –

我们可以看到我们现在有两个池, pool0为raid0, pool1为raid1。

要检查池的状态,我们可以使用以下命令:


# zpool status
pool: pool0
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
pool0 ONLINE 0 0 0
sdb ONLINE 0 0 0
errors: No known data errors
pool: pool1
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
pool1 ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
errors: No known data errors

我们可以使用“zpool status”命令检查池状态。 我们可以看到pool0和pool1之间的区别,pool0只有一个磁盘,pool1有两个磁盘,磁盘状态为mirror(mirror-0)。

接下来,我们将使用RAID-Z创建一个池,RAID-Z是像RAID-5这样的数据/奇偶校验分配方案,但它使用动态条带宽度:每个块都具有自己的RAID条带,无论块大小如何,导致每个RAID-Z写入都是全条带写入。

RAID-Z需要至少三个硬盘驱动器,并且是RAID 0和RAID 1之间的妥协。在RAID-Z池中:如果池中的单个磁盘死机,则只需替换该磁盘,ZFS将自动重建数据基于来自其他磁盘的奇偶校验信息。 要松开存储池中的所有信息,两个磁盘将不得不死亡。 为了使驱动器设置更加冗余,您可以使用RAID 6(在ZFS情况下为RAID-Z2)获得双重奇偶校验。

我们先创建一个奇偶校验的RAID-Z池。


# zpool create -f poolz1 raidz sde sdf sdg
# zpool list poolz1
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
poolz1 5.94G 117K 5.94G – 0% 0% 1.00x ONLINE –

# zpool status poolz1
pool: poolz1
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
poolz1 ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
sdg ONLINE 0 0 0
errors: No known data errors

# df -h /poolz1
Filesystem Size Used Avail Use% Mounted on
poolz1 3.9G 0 3.9G 0% /poolz1

我们可以看到,df -h显示我们的6GB池已经减少到4GB,2GB被用于保存奇偶校验信息。 使用zpool status命令,我们看到我们的池现在正在使用RAID-Z。

接下来我们将创建RAID-Z2(raid 6),为此,我们必须删除现有的池,因为没有更多的磁盘可用。 删除池很容易,我们可以使用zpool destroy命令。


# zpool list
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
pool0 1.98G 64K 1.98G – 0% 0% 1.00x ONLINE –
pool1 1.98G 64K 1.98G – 0% 0% 1.00x ONLINE –
poolz1 5.94G 117K 5.94G – 0% 0% 1.00x ONLINE –

# zpool destroy pool0
# zpool destroy pool1
# zpool destroy poolz1
# zpool list
no pools available

现在我们所有的zpool都没有了,所以我们可以创建一个RAID-Z2池。


# zpool create poolz2 raidz2 sdb sdc sdd sde
# zpool list
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
poolz2 7.94G 135K 7.94G – 0% 0% 1.00x ONLINE –

# df -h /poolz2
Filesystem Size Used Avail Use% Mounted on
poolz2 3.9G 0 3.9G 0% /poolz2

# zpool status poolz2
pool: poolz2
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
poolz2 ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
sde ONLINE 0 0 0
errors: No known data errors

我们可以看到,df -h显示,我们的8GB池已经减少到4GB,因为4GB被用于持有奇偶校验信息两次。 使用“zpool status”命令,我们看到我们的池现在使用RAID-Z2。

4、创建和配置ZFS文件系统

在下一步中,我们将创建和配置ZFS文件系统。


# zfs list
NAME USED AVAIL REFER MOUNTPOINT
poolz2 105K 3.83G 26.1K /poolz2

我们已经有一个ZFS文件系统,当我们创建zpool时,这个文件系统会自动添加。 现在我们将创建另一个ZFS文件系统。


# zfs create poolz2/tank
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
poolz2 132K 3.83G 26.1K /poolz2
poolz2/tank 25.4K 3.83G 25.4K /poolz2/tank

# df -h | grep poolz2
poolz2 3.9G 128K 3.9G 1% /poolz2
poolz2/tank 3.9G 128K 3.9G 1% /poolz2/tank

我们创建一个名为tank的新的ZFS文件系统,并自动将其安装为/ poolz2 / tank 。

如何为ZFS文件系统创建自定义安装点? 使用以下命令:


# zfs create poolz2/data -o mountpoint=/data
# df -h | grep poolz2
poolz2 3.9G 0 3.9G 0% /poolz2
poolz2/tank 3.9G 0 3.9G 0% /poolz2/tank
poolz2/data 3.9G 0 3.9G 0% /data

如何修改现有的mountpoint? 我们可以通过以下命令来做到这一点:


# zfs set mountpoint=/tank poolz2/tank
# df -h | grep poolz2
poolz2 3.9G 0 3.9G 0% /poolz2
poolz2/data 3.9G 0 3.9G 0% /data
poolz2/tank 3.9G 0 3.9G 0% /tank

要安装和卸载文件系统,请使用以下命令:


# zfs unmount /data
# df -h | grep poolz2
poolz2 3.9G 0 3.9G 0% /poolz2
poolz2/tank 3.9G 0 3.9G 0% /tank

# zfs mount poolz2/data
# df -h | grep poolz2
poolz2 3.9G 0 3.9G 0% /poolz2
poolz2/tank 3.9G 0 3.9G 0% /tank
poolz2/data 3.9G 0 3.9G 0% /data

删除zfs文件系统非常容易,我们可以使用命令zfs destroy来进行。


# zfs destroy poolz2/data
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
poolz2 152K 3.83G 26.1K /poolz2
poolz2/tank 25.4K 3.83G 25.4K /tank

文件系统/数据已经没了。

结论

ZFS文件系统是一个革命性的新文件系统,从根本上改变了在类Unix操作系统上管理文件系统的方式。 ZFS提供了在今天可用的任何其他文件系统中找不到的功能和优点。 ZFS是强大的,可扩展的,易于管理。

NextCloud安全检测工具

数据安全是个大问题。去年,Dropbox的6800万个账户丢失了数据,雅虎有不少于10亿的帐户受损。Nextcloud提供了一个在线的Nextcloud安全性检测工具,它可以自动访问你的Nextcloud实例、分析安全状况。

数据安全是个大问题。去年,Dropbox的6800万个账户丢失了数据,雅虎有不少于10亿的帐户受损。Nextcloud提供了一个在线的Nextcloud安全性检测工具,它可以自动访问你的Nextcloud实例、分析安全状况。

Nextcloud Security Scan会检查以下项目:

  • 程序漏洞
  • 安全强化状况
  • 服务器安全

Nextcloud Security Scan地址:https://scan.nextcloud.com/

Nextcloud Security Scan

 

使用方法很简单,在URL一栏输入你的Nextcloud地址,点击“Scan”,稍等片刻就能显示出结果。

Nextcloud Security Scan Result

 

评价等级

  • F = 服务器版本已经淘汰,并且没有任何漏洞修复程序。服务器内的数据极易被窃取,服务器极易被控制。
  • E =此服务器受到至少一个高危漏洞的威胁。很容易遭到侵入而被窃取数据甚至接管服务器。
  • D =此服务器受到至少一个中等漏洞的威胁。攻击者可以通过特殊URL欺骗访问者而盗取其信息,攻击者可能会窃取数据甚至接管服务器。
  • C =此服务器受到至少一个低危漏洞的影响。这可能或可能不会为攻击者提供侵入的途径,可能需要一些额外的漏洞来利用它们。
  • A =这个服务器没有已知的漏洞,可以更新版本以使攻击者更加难以利用未知的漏洞进行破解。
  • A+ =该服务器是最新的,配置良好,并具有行业领先的强化功能,使攻击者难以利用未知的漏洞进行破解。了解更多有关信息:https://nextcloud.com/blog/nextcloud-11-delivers-verified-security-improvements/

安全建议

  • 采用HTTPS链接并启用HSTS
  • 设置好文件夹权限
  • 及时将Nextcloud/ownCloud更新至最新版本
  • 及时修复Apache/NGINX、PHP、MySQL的漏洞
  • 及时更新服务器系统

Nextcloud 12 正式版发布

2016年4月27日,ownCloud联合创始人Frank Karlitschek宣布离开ownCloud ltc.,转而成立另一家公司“Nextcloud”。由于ownCloud程序本身归其开发人员所有,所以Nextcloud可以直接使用ownCloud的核心技术。Nextcloud作为ownCloud的衍生版本,在其基础上做了许多改进。
经过5个月的开发和三个星期的密集测试,Nextcloud 12正式版发布。

2016年4月27日,ownCloud联合创始人Frank Karlitschek宣布离开ownCloud ltc.,转而成立另一家公司“Nextcloud”。由于ownCloud程序本身归其开发人员所有,所以Nextcloud可以直接使用ownCloud的核心技术。Nextcloud作为ownCloud的衍生版本,在其基础上做了许多改进。

经过5个月的开发和三个星期的密集测试,Nextcloud 12正式版发布。

Nextcloud 12

下载地址:https://nextcloud.com/install

更新方法

以下用于从nextcloud低版本升级到当前版本

1、ssh登陆到nextcloud服务器,并进入nextcloud的update文件夹

2、用PHP运行updater.phar文件

sudo -u www-data php updater.phar

3、运行上述命令后会显示更新向导,根据该更新向导操作即可。

手动升级owncloud

owncloud版本:9.1.4升级9.1.5

1、备份

1.1 进入owncloud根目录

cd /var/www/owncloud

1.2 备份config和apps文件夹

将config和apps备份到backup文件夹下:


mkdir backup

rsync -Aax config apps ./backup

1.3 备份数据库


mysqldump --lock-tables -h "server" -u "username" -p"password" "db_name" owncloud_dbbackup.bak

2 打开维护模式

sudo -u www-data php occ maintenance:mode --on

3 下载最新版本的owncloud

下载地址:https://owncloud.org/install/


cd /var/www
wget http://download.owncloud.org/community/owncloud-latest.tar.bz2

4  将own cloud解压缩到 owncloud_latest 文件夹


mkdir owncloud_latest
tar -C owncloud_latest

5、将最新源代码覆盖到旧的代码目录下

rsync --inplace -rtv owncloud_latest/owncloud/ owncloud/

6 删除多余文件

rm -rf owncloud-latest.tar.bz2 owncloud_latest/

7 升级数据库、关闭维护模式

cd /var/www/owncloud
sudo -u www-data php occ upgrade
sudo -u www-data php occ maintenance:mode --off

Gen8安装Exsi绕坑总结和方案选择

考虑到目前黑群晖 Hyper-V 的引导遥遥无期,而且被 Chiphell 上各位大神各种安利,加上确实 Windows Server 作为 Gen8 的宿主机太浪费资源,因此摸索着给 Gen8 上了 Esxi 系统,其中遇到了不少坎坷,在此做个总结,后续准备写一个关于 Gen8 上的系列教程,便于后人踩坑。

一、硬件方案选择

目前在 Gen8 上部署 Esxi 的话,大致有如下几个核心方案可供选择:

  • Gen8 自带的 B120i 使用模式的选择:AHCI or Raid?
  • 虚拟机存储使用 VMFS or RDM or 直通?
  • 是否需要加 HBA 卡?

其实这两个问题有一些先后关联关系,要回答这些问题,就不得不说下 Gen8 上面的一些 Esxi 的坑了……

第一个坑,就是 Gen8 上 B120i Raid 驱动的性能问题,目前从各大论坛(不论中外)上大致都能搜索到非常多的 Gen8 Esxi Raid 驱动导致的磁盘性能低下的问题,在 Esxi 6.0和5.5系统上,解决方案基本都是把驱动进行降级,但是到了6.5的系统会发现老的驱动和系统并不兼容,也就是说除非 HP 官方给出新的驱动(目前最新的102版本的驱动尚未解决这个问题),否则在 Esxi 6.5 系统上,B120i 使用 Raid 模式是无解的,所以第一个问题解决了,那就是 B120i 只能使用 AHCI 模式。

第二个坑,就是 Esxi 6.5开始自带的新的 AHCI 的 Native 驱动存在性能问题,我也真是醉了,好歹大家都是企业级的大厂,一个驱动都解决不好……参考了 NXHut 的解决方案(点击这里查看原文),在 Esxi 的 SSH 中使用如下命令禁用 Native 的 AHCI 驱动,即可暂时解决这个问题,也不知道 Vmware 能否在下个 Update 来修复。

esxcli system module set --enabled=false --module=vmw_ahci

第三个坑,就是 HP 定制的 Esxi 官方镜像和 RDM 的兼容性问题。参考网友的一些反馈和我自己的亲身经历……我一开始期望使用 RDM 这种“假直通”的方式来把我 Gen8 中的硬盘给到群晖使用,但是每次都出现虚拟机直接卡死的状况,这个时候连 Esxi 都没有办法正常关机,只能通过按住电源键强制关机的方式来解决这个问题(根据网友的测试,使用 Vmware 原版镜像就 OK,但是这样就没有集成 HP 的一些驱动和优化),因此针对第二个问题,RDM 这条路也是走不通了。

基于上面这些坑,那就还剩下一个问题需要回答,那就是使用 Vmware 的 VMFS 还是直通,如果选择直通就意味着你必须要购买一张 HBA 卡(因为 Esxi 的限制只能直通整个设备而非某个硬盘,如果 Gen8 直通 SATA 管理器的话,那你就没有硬盘可以用来作为存储池安装虚拟机了)。

这个问题的选择就没有坑的限制了,如果你希望先以节约成本体验整个模式,那么完全可以用 VMFS 解决这个问题,只是在性能上会有一些损耗,如果你有一些预算(其实不贵,目前一张 Lsi 9211-8i 的卡在淘宝上大约在400人民币左右),那么还是建议你购买一张 HBA 卡然后直通给你的虚拟机用,这样一来硬盘拆下来直接换其他机器也能用,二来性能得到了最优的发挥。

总结一下,我最终选择的硬件方案如下:

  • Gen8 B120i 工作在 AHCI 模式,并购买了一个 SAS 转 SATA 的线把 SSD 放到了 Port1(目的是为了享受 SATA3 的接口速度),记得要在 Gen8 的 Bios 中打开 Write Cache,否则写入性能会很差
  • 购买了 HBA 卡(LSI 9211-8i),刷了 IT 模式,把 Gen8 的四个硬盘接到 HBA 卡上,后续直通给虚拟机

二、存储方案选择

存储方案的选择,目前大概有两种方案:

  • 直接使用群晖搭建存储中心
  • 使用 ZFS 搭建存储中心,群晖作为应用服务,使用 NFS 来挂载 ZFS 上的存储

说到这里,不得不谈下 ZFS 这个牛逼的文件系统了,ZFS是SUN为Solaris操作系统开发的一个高级的文件系统,可以用相对简单的方式提供安全的冗余存储服务。我对ZFS的理解也不深,只能借用网上的介绍:“ZFS 文件系统是一个革命性的全新的文件系统,它从根本上改变了文件系统的管理方式,这个文件系统的特色和其带来的好处至今没有其他文件系统可以与之媲美,ZFS 被设计成强大的、可升级并易于管理的”。简而言之,反正就是很高大上就对了。

但是,这里必须要说的就是但是……ZFS 不论从可靠性、性能等层面,都是数一数二的,但是会有一个致命的问题,那就是对内存的大量需求,目前 ZFS 官方推荐的每 TB 的存储需要搭配至少 1G 的内存才能发挥出最大的优势,最佳的配比是 1TB 存储配 6G 内存,这个对于内存非常紧张的 Gen8 来说就有一些捉襟见肘了。

因此最终,我选择了直接使用群晖来搭建整个存储中心,把 HBA 卡直通给群晖,系统中的4+4+3+3的10T 存储交给群晖做了 SHR 的 Raid,并使用一块硬盘作为数据冗余,这样实际可用的空间大概是9T 左右。

转载自:Gen8安装Exsi绕坑总结和方案选择

创建原版Minecraft服务器

Minecraft现在变得越来越火了,但是大多数人还在自己单机。想要进入服务器又苦于找不到好的亦或是厌烦各种可恶的规矩。那还在等什么?自己建一个吧!

以下将以Linux为例

1、使用ssh登陆购买linux服务器

选择合适的工具

  • MAC OS 打开终端
  • Windows 大家可以百度下有什么可以有的ssh工具
  • Linux 你当然是知道的

输入以下命令登陆linux服务器


ssh [user]@[ip_address] -p [port]

2. 下载你中意的服务器版本

官方minecraft服务器版本下载地址:minecraft_server

3、 编写启动脚本

具体步骤如下:

创建一个文件夹放置服务器文

mkdir minecratr_server
mv minecraft_server*.jar ./minecratr_server/minecraft_server.jar

使用文本编辑器创建脚本文件

cd minecratr_server
vim minecraft_server.sh

添加以下内容

#!/bin/bash
java -Xmx1024M -Xms512M -jar minecraft_server.jar

设置执行权限

chmod +x minecraft_server.sh

4. 第一次启动服务器

启动服务器

./minecraft_server.sh

等待服务器退出


[21:13:34] [Server thread/INFO]: Starting minecraft server version 1.11.2
[21:13:34] [Server thread/INFO]: Loading properties
[21:13:34] [Server thread/WARN]: server.properties does not exist
[21:13:34] [Server thread/INFO]: Generating new properties file
[21:13:34] [Server thread/WARN]: Failed to load eula.txt
[21:13:34] [Server thread/INFO]: You need to agree to the EULA in order to run the server. Go to eula.txt for more info.
[21:13:34] [Server thread/INFO]: Stopping server

同意EULA

vim eula.txt

将eula=false改为eula=true
再次启动服务器

./minecraft_server.sh

等待加载完成后,关闭服务器。


[21:14:53] [Server thread/INFO]: Starting minecraft server version 1.11.2
[21:14:53] [Server thread/INFO]: Loading properties
[21:14:53] [Server thread/INFO]: Default game type: SURVIVAL
[21:14:53] [Server thread/INFO]: Generating keypair
[21:14:53] [Server thread/INFO]: Starting Minecraft server on *:25565
[21:14:53] [Server thread/INFO]: Using epoll channel type
[21:14:53] [Server thread/WARN]: Failed to load user banlist:
java.io.FileNotFoundException: banned-players.json (没有那个文件或目录)
at java.io.FileInputStream.open0(Native Method) ~[?:1.8.0_111]
at java.io.FileInputStream.open(FileInputStream.java:195) ~[?:1.8.0_111]
at java.io.FileInputStream.<init>(FileInputStream.java:138) ~[?:1.8.0_111]
at com.google.common.io.Files.newReader(Files.java:86) ~[minecraft_server.jar:?]
at mx.g(SourceFile:136) ~[minecraft_server.jar:?]
at lg.z(SourceFile:99) [minecraft_server.jar:?]
at lg.<init>(SourceFile:25) [minecraft_server.jar:?]
at lh.j(SourceFile:186) [minecraft_server.jar:?]
at net.minecraft.server.MinecraftServer.run(SourceFile:436) [minecraft_server.jar:?]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_111]
[21:14:53] [Server thread/WARN]: Failed to load ip banlist:
java.io.FileNotFoundException: banned-ips.json (没有那个文件或目录)
at java.io.FileInputStream.open0(Native Method) ~[?:1.8.0_111]
at java.io.FileInputStream.open(FileInputStream.java:195) ~[?:1.8.0_111]
at java.io.FileInputStream.<init>(FileInputStream.java:138) ~[?:1.8.0_111]
at com.google.common.io.Files.newReader(Files.java:86) ~[minecraft_server.jar:?]
at mx.g(SourceFile:136) ~[minecraft_server.jar:?]
at lg.y(SourceFile:91) [minecraft_server.jar:?]
at lg.<init>(SourceFile:27) [minecraft_server.jar:?]
at lh.j(SourceFile:186) [minecraft_server.jar:?]
at net.minecraft.server.MinecraftServer.run(SourceFile:436) [minecraft_server.jar:?]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_111]
[21:14:53] [Server thread/WARN]: Failed to load operators list:
java.io.FileNotFoundException: ops.json (没有那个文件或目录)
at java.io.FileInputStream.open0(Native Method) ~[?:1.8.0_111]
at java.io.FileInputStream.open(FileInputStream.java:195) ~[?:1.8.0_111]
at java.io.FileInputStream.<init>(FileInputStream.java:138) ~[?:1.8.0_111]
at com.google.common.io.Files.newReader(Files.java:86) ~[minecraft_server.jar:?]
at mx.g(SourceFile:136) ~[minecraft_server.jar:?]
at lg.A(SourceFile:107) [minecraft_server.jar:?]
at lg.<init>(SourceFile:29) [minecraft_server.jar:?]
at lh.j(SourceFile:186) [minecraft_server.jar:?]
at net.minecraft.server.MinecraftServer.run(SourceFile:436) [minecraft_server.jar:?]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_111]
[21:14:53] [Server thread/WARN]: Failed to load white-list:
java.io.FileNotFoundException: whitelist.json (没有那个文件或目录)
at java.io.FileInputStream.open0(Native Method) ~[?:1.8.0_111]
at java.io.FileInputStream.open(FileInputStream.java:195) ~[?:1.8.0_111]
at java.io.FileInputStream.<init>(FileInputStream.java:138) ~[?:1.8.0_111]
at com.google.common.io.Files.newReader(Files.java:86) ~[minecraft_server.jar:?]
at mx.g(SourceFile:136) ~[minecraft_server.jar:?]
at lg.C(SourceFile:123) [minecraft_server.jar:?]
at lg.<init>(SourceFile:30) [minecraft_server.jar:?]
at lh.j(SourceFile:186) [minecraft_server.jar:?]
at net.minecraft.server.MinecraftServer.run(SourceFile:436) [minecraft_server.jar:?]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_111]
[21:14:53] [Server thread/INFO]: Preparing level "world"
[21:14:54] [Server thread/INFO]: Preparing start region for level 0
[21:14:55] [Server thread/INFO]: Preparing spawn area: 5%
[21:14:56] [Server thread/INFO]: Preparing spawn area: 10%
[21:14:57] [Server thread/INFO]: Preparing spawn area: 14%
[21:14:58] [Server thread/INFO]: Preparing spawn area: 20%
[21:14:59] [Server thread/INFO]: Preparing spawn area: 26%
[21:15:00] [Server thread/INFO]: Preparing spawn area: 33%
[21:15:01] [Server thread/INFO]: Preparing spawn area: 41%
[21:15:02] [Server thread/INFO]: Preparing spawn area: 49%
[21:15:03] [Server thread/INFO]: Preparing spawn area: 57%
[21:15:04] [Server thread/INFO]: Preparing spawn area: 68%
[21:15:05] [Server thread/INFO]: Preparing spawn area: 76%
[21:15:06] [Server thread/INFO]: Preparing spawn area: 86%
[21:15:07] [Server thread/INFO]: Preparing spawn area: 96%
[21:15:08] [Server thread/INFO]: Done (14.531s)! For help, type "help" or "?"

更改服务器配置文件

vim server.properties

server.properties配置方法:server.properties
正式启动服务器

screen ./minecraft_server.sh

到此服务器建立完毕,开始享用吧!
参考:如何建立一个自己的Minecraft服务器 【原版】