Linux 环境下制作启动盘
最近有点迷 ARPG,但是自己的 T470P 上只有一个 Ubuntu 系统,所以买了一个 2422 的固态往上面装个 Win10,Linux 下构建启动盘还是蛮多坑的,下面记录一下操作流程,免得以后忘了。
最近有点迷 ARPG,但是自己的 T470P 上只有一个 Ubuntu 系统,所以买了一个 2422 的固态往上面装个 Win10,Linux 下构建启动盘还是蛮多坑的,下面记录一下操作流程,免得以后忘了。
Collect, report, or save system activity information.
根据要统计的信息类型的不同,输出格式也不同。
1 | # 查看全天 |
CPU统计信息输出格式:
1 | # 查看全天 |
内存统计信息输出格式
1 | # 查看全天 |
IO信息输出格式
1 | # 查看全天 |
流量信息输出格式:
1 | head -n 1 /etc/issue |
1 | uname -a |
1 | hostname |
1 | lspci -tv |
1 | lsusb -tv |
1 | lsmod |
1 | cat /proc/cpuinfo |
查看进程状态。
| 参数 | 作用 |
|---|---|
| -a | 显示所有的进程(包括其他用户的) |
| -u | 用户以及其他详细信息 |
| -x | 显示没有控制终端的进程 |
1 | ps -ef |
linux 系统中进程最常见的 5 种状态为:
当执行”ps aux”命令后通常会看到下面格式的进程状态,表格中只是列举了部分输出值,而且正常的输出值中不包括中文注释部分:
| USER | PID | %CPU | %MEM | VSZ | RSS | TTY | STAT | START | TIME | COMMAND |
|---|---|---|---|---|---|---|---|---|---|---|
| 进程的所有者 | 进程 ID 号 | 运算器占用率 | 内存占用率 | 虚拟内存使用量(单位是 KB) | 占用的固定内存量(单位是 KB) | 所在终端 | 进程状态 | 被启动的时间 | 实际使用 CPU 的时间 | 命令名称与参数 |
| root | 1 | 0.0 | 0.4 | 53684 | 7628 | ? | Ss | 07:22 | 0:02 | /usr/lib/systemd/systemd |
| root | 2 | 0.0 | 0.0 | 0 | 0 | ? | S | 07:22 | 0:00 | [kthreadd] |
| root | 3 | 0.0 | 0.0 | 0 | 0 | ? | S | 07:22 | 0:00 | [ksoftirqd/0] |
| root | 5 | 0.0 | 0.0 | 0 | 0 | ? | S< | 07:22 | 0:00 | [kworker/0:0H] |
| root | 7 | 0.0 | 0.0 | 0 | 0 | ? | S | 07:22 | 0:00 | [migration/0] |
查询某个指定服务的进程 PID 号码值,比如
1 | pidof firefox |
终止某个指定 PID 号码的进程
1 | $ kill <PID> |
终止某个指定名称的服务所对应的全部进程,因为一般大型软件的服务程序通常都会有数个进程协同为其提供服务,如果逐个去结束 PID 实在麻烦,所以可以使用 killall 命令来批量结束某个服务程序的全部进程,比如
1 | $ killall httpd |
top 命令是 Linux 下常用的性能分析工具,能够动态监视进程活动与系统负载等信息,类似于 Windows 的任务管理器
可以直接使用 top 命令后,查看%MEM 的内容。可以选择按进程查看或者按用户查看,如想查看 oracle 用户的进程内存使用情况的话可以使用如下的命令:
1 | $ top -u oracle |
示例输出如下:
1 | top - 17:59:11 up 289 days, 5:57, 20 users, load average: 0.01, 0.02, 0.05 |
前面的五行为系统整体的统计信息,下面我们来逐行的讲解:
11.2 id意味着有 11.2%的 CPU 资源是空闲的。后面每行是进程的统计数据,其中:
PID:进程的 ID
USER:进程所有者
PR:进程的优先级别,越小越优先被执行
NInice:值
VIRT:进程占用的虚拟内存
RES:进程占用的物理内存
SHR:进程使用的共享内存
S:进程的状态。S 表示休眠,R 表示正在运行,Z 表示僵死状态,N 表示该进程优先值为负数
%CPU:进程占用 CPU 的使用率
%MEM:进程使用的物理内存和总内存的百分比
TIME+:该进程启动后占用的总的 CPU 时间,即占用 CPU 使用时间的累加值。
COMMAND:进程启动命令名称
常用的命令:
P:按%CPU 使用率排行
T:按 MITE+排行
M:按%MEM 排行
可以根据进程查看进程相关信息占用的内存情况,(进程号可以通过 ps 查看)如下所示:
1 | $ pmap -d 14596 |
查看内存总量和空闲内存量
1 | $ grep MemTotal /proc/meminfo |
内存和交换分区容量及使用情况
1 | $ free |
total:总计内存量
used:已用量
free:可用量
shared:进程共享的内存量
buffers:磁盘缓存的内存量
cached:缓存的内存量
TODO
硬盘分区使用情况
1 | df |
查看某个目录的大小
1 | du -sh <目录> |
TODO
获取网卡配置与网络状态等信息
1 | $ ifconfig |
注意每段开头的网卡名称、inet 参数后面的 IP 地址、ether 参数后面的物理 mac 地址,以及 RX、TX 的接受与发送数据包的大小

TODO
如果发现自己的 java 进程悄无声息的消失了,几乎没有留下任何线索,那么 dmesg 一发,很有可能有你想要的。
1 | sudo dmesg|grep -i kill|less |
去找关键字 oom_killer。找到的结果类似如下:
1 | [6710782.021013] java invoked oom-killer: gfp_mask=0xd0, order=0, oom_adj=0, oom_scoe_adj=0 |
以上表明,对应的 java 进程被系统的 OOM Killer 给干掉了,得分为 854.
解释一下 OOM killer(Out-Of-Memory killer),该机制会监控机器的内存资源消耗。当机器内存耗尽前,该机制会扫描所有的进程(按照一定规则计算,内存占用,时间等),挑选出得分最高的进程,然后杀死,从而保护机器。
dmesg 日志时间转换公式:
log 实际时间=格林威治 1970-01-01+(当前时间秒数-系统启动至今的秒数+dmesg 打印的 log 时间)秒数:
1 | date -d "1970-01-01 UTC `echo "$(date +%s)-$(cat /proc/uptime|cut -f 1 -d' ')+12288812.926194"|bc ` seconds" |
剩下的,就是看看为什么内存这么大,触发了 OOM-Killer 了。
系统负载
1 | $ cat /proc/loadavg |
包括当前系统时间、系统已运行时间、当前在线用户、平均负载值等。
平均负载值指的是最近 1/5/15 分钟的系统压力情况,负载值越低越好,尽量不要长期超过 1。
1 | $ uptime |
配合 watch 命令来每秒刷新一次来获得当前系统负载情况:
1 | watch -n 1 uptime |
TODO
TODO
Linux 命令尤其多,没办法一下子全部搞明白,下面来不及看的部分我就用 TODO 标出了。
原来:负载均衡器会根据配好的 IP 和主机名来进行负载均衡,但是对 AWS cloud 这样体量的系统来说,因为服务实例宕机恢复十分频繁,所以负载均衡器还会有一个更复杂的注册 / 注销服务的机制。
现在:Eureka 在中间层提供一种负载均衡的可能。
| Feature | Consul | zookeeper | etcd | euerka |
|---|---|---|---|---|
| 服务健康检查 | 服务状态,内存,硬盘等 | (弱)长连接,keepalive | 连接心跳 | 可配支持 |
| 多数据中心 | 支持 | — | — | — |
| kv存储服务 | 支持 | 支持 | 支持 | — |
| 一致性 | raft | paxos(zab) | raft | — |
| cap | ca | cp | cp | ap |
| 使用接口(多语言能力) | 支持http和dns | 客户端 | http/grpc | http(sidecar) |
| watch支持 | 全量/支持long polling | 支持 | 支持 long polling | 支持 long polling/大部分增量 |
| 自身监控 | metrics | — | metrics | metrics |
| 安全 | acl /https | acl | https支持(弱) | — |
| spring cloud集成 | 已支持 | 已支持 | 已支持 | 已支持 |
Euraka 使用时需要显式配置健康检查支持;Zookeeper,Etcd 则在失去了和服务进程的连接情况下任务不健康,而 Consul 相对更为详细点,比如内存是否已使用了90%,文件系统的空间是不是快不足了。
Consul 通过 WAN 的 Gossip 协议,完成跨数据中心的同步;而且其他的产品则需要额外的开发工作来实现。
除了 Eureka ,其他几款都能够对外支持 k-v 的存储服务,所以后面会讲到这几款产品追求高一致性的重要原因。而提供存储服务,也能够较好的转化为动态配置服务哦。
Eureka 典型的 AP,作为分布式场景下的服务发现的产品较为合适,服务发现场景的可用性优先级较高,一致性并不是特别致命。其次 CA 类型的场景 Consul,也能提供较高的可用性,并能 k-v store 服务保证一致性。 而Zookeeper,Etcd则是CP类型 牺牲可用性,在服务发现场景并没太大优势。
Zookeeper的跨语言支持较弱,其他几款支持 http11 提供接入的可能。Euraka 一般通过 sidecar的方式提供多语言客户端的接入支持。Etcd 还提供了Grpc的支持。 Consul除了标准的Rest服务api,还提供了DNS的支持。
Zookeeper 支持服务器端推送变化,Eureka 2.0(正在开发中)也计划支持。 Eureka 1,Consul,Etcd则都通过长轮询的方式来实现变化的感知。
除了 Zookeeper ,其他几款都默认支持 metrics,运维者可以搜集并报警这些度量信息达到监控目的。
Consul,Zookeeper 支持ACL,另外 Consul,Etcd 支持安全通道https。
目前都有相对应的 boot starter,提供了集成能力。
总的来看,目前Consul 自身功能,和 spring cloud 对其集成的支持都相对较为完善,而且运维的复杂度较为简单(没有详细列出讨论),Eureka 设计上比较符合场景,但还需持续的完善。


Eureka Client 将信息注册到 Eureka Server,注册过程发生在第一次心跳时(在 30 秒后)。
正常情况下,Client 必须显式调用 Unregister 来释放自己的注册信息,除非是由于”unclean termination”而导致心跳丢失超过 3 次。
客户端每30秒通过发送一次心跳(heartbeats)来续约(renewal),心跳告知Eureka Server本实例仍然存活,如果Server在90秒内没有收到续约请求,它将从服务注册表中移除该实例。
Eureka clients fetches the registry information from the server and csort_bufferhes it locally. After that, the clients use that information to find other services. This information is updated periodically (every 30 seconds) by getting the delta updates between the last fetch cycle and the current one. The delta information is held longer (for about 3 mins) in the server, hence the delta fetches may return the same instances again. The Eureka client automatically handles the duplicate information.
After getting the deltas, Eureka client reconciles the information with the server by comparing the instance counts returned by the server and if the information does not match for some reason, the whole registry information is fetched again. Eureka server caches the compressed payload of the deltas, whole registry and also per application as well as the uncompressed information of the same. The payload also supports both JSON/XML formats. Eureka client gets the information in compressed JSON format using jersey apache client.
Eureka client sends a cancel request to Eureka server on shutdown. This removes the instance from the server’s instance registry thereby effectively taking the instance out of traffic.
This is done when the Eureka client shuts down and the application should make sure to call the following during its shutdown.
DiscoveryManager.getInstance().shutdownComponent()
All operations from Eureka client may take some time to reflect in the Eureka servers and subsequently in other Eureka clients. This is because of the caching of the payload on the eureka server which is refreshed periodically to reflect new information. Eureka clients also fetch deltas periodically. Hence, it may take up to 2 mins for changes to propagate to all Eureka clients.
Eureka Client默认使用Jersey发送基于Jackson封装的JSON数据包给Eureka Server。
Eureka 不限制通信协议,Thrift、HTTP(S)等均可。
Eureka Client 的高可用设计:
Eureka Server 的高可用设计:
Renewal Threshold并开始接收 Client 的心跳;Renews(last min)(上一分钟内收到的心跳次数)达到了Renews threshold(Server 期望在每分钟中收到的心跳次数,一般是 3),或者过去 15 分钟内的统计数据小于eureka.server.renewalPercentThreshold(renews / renews threshold 的比值,默认为 0.85,当在 15 分钟内微服务心跳数低于 85%,则 Server 会进入自我保护状态,在这种情况下 Server 不会删除注册信息),则进入保护模式,自我保护状态其实是为了防止突发网络不稳定或断电时微服务心跳数剧减,导致微服务注册信息被大量删除的情况。Renews达到了Renews threshold;eureka.server.enableSelfPreservation=false。orphaned server,一些 Client 会注册到这些 Server 上,导致一些 Client 能看到这些注册信息而其他的一些则不能。比如在测试环境中出现:
1 | EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE. |
解决办法:
配置:
Configuring Eureka
Eureka Server 开放的 REST 接口提供动态配置功能:
Eureka REST operations
静态设置:
1 | eureka.metadata.mykey=myvalue |
设置后,相当于将mykey:myvalue添加到 eureka 的metadata map中。
动态设置:
需要提供一个自定义的
获取:
1 | String myValue = instanceInfo.getMetadata().get("myKey"); |
EurekaClient
ExampleEurekaGovernatedService
DefaultEurekaClientConfig extends EurekaClientConfig
EurekaServerConfig extends DefaultEurekaServerConfig
CloudInstanceConfig extends PropertiesInstanceConfig
MyDataCenterInstanceConfig extends PropertiesInstanceConfig
To dynamically do this, you will need to first provide your own custom implementation of the EurekaInstanceConfig interface. You can then overload the public Map<String, String> getMetadataMap() method to return a metadata map that contains the desired metadata values. See PropertiesInstanceConfig for an example implementation that provides the configuration based system above.

Zuul 基于 Netty 开发,使用 filters 包含了核心业务逻辑,Filter 是使用 Groovy 写的,主要是为了提供动态编译加载的能力,filters 主要包含了三类:
ProxyEndpoint filter will route the request to the origin.HttpInboundSyncFilter或HttpOutboundSyncFilter来实现一种同步 Filter,例子见Zuul 源码中的Routes.groovy;HttpInboundFilter或HttpOutboundFilter,例子见Zuul 源码中的SampleServiceFilter.groovy。Type: most often defines the stage during the routing flow when the Filter will be applied (although it can be any custom string)
Async: define if the filter is sync or async, generally meaning do you need to make an external call or just doing work on-box
Execution Order: applied within the Type, defines the order of execution across multiple Filters
Criteria: the conditions required in order for the Filter to be executed
Action: the action to be executed if the Criteria is met
这些例子是zuul-sample中的代码。
默认情况下 Zuul 不会缓存请求体,因为 Filter 一般用到请求头就够了,但是如果需要在 inbound 中用到请求头或在 outbound 中用到响应头,则需要明确指定 Zuul 缓存,可以重写 Filter 的needsBodyBuffered():
1 | @Override |
Zuul 支持修改暴露服务时使用的协议,使用方法见 sample 项目中的SampleServerStartup。
Push Messaging 机制可以支持从 Server 端推送消息到 Client 端,支持两种协议:WebSockets 和 Server Sent Events (SSE)。
Push Messaging
TODO
原生 API 如何使用见:Netflix / ribbon - Getting Started
如果是搭配 Spring Boot,可以参考 Spring Could 文档。
a logic component to determine which server to return from a list
a component running in background to ensure liveness of servers
this can be static or dynamic. If it is dynamic (as used by DynamicServerListLoadBalancer), a background thread will refresh and filter the list at certain interval
BaseLoadBalancer.setServerList()中。Archaius ConfigurationManager来设置 Server 列表。1 | myClient.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList |
ServerListFilter 是DynamicServerListLoadBalancer的组件,用于过滤从ServerList返回的服务器列表,现在有两种实现:
1 | myclient.ribbon.EnableZoneAffinity=true |
ServerList返回的全体服务器的一个固定子集,如果有服务器可用性较弱,则可以定期用新服务器替换老服务器。可以通过设置以下属性启用该Filter: 1 | myClient.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList |
com.netflix.loadbalancer.DynamicServerListLoadBalancer#updateListOfServers
com.netflix.loadbalancer.ServerList#getUpdatedListOfServers
com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList#obtainServersViaDiscovery
TODO
虚拟化技术将一台服务器虚拟出多个虚拟机来提供服务。
虚拟化技术包括计算虚拟化(服务器虚拟化)、存储虚拟化、网络虚拟化等。
在实际讲解虚拟化之前,我们需要先解释一下隔离技术,在隔离的基础上我们才能任意粒度、自由地分配资源。
记录一些平时看到或用过的 shell 脚本技巧和代码片段。
Kubernetes Master 主要负责管理集群,它会协调集群内的所有活动,包括:scheduling applications, maintaining applications’ desired state, scaling applications, and rolling out new updates。
Master 实际上是三个进程的集合,它们运行在集群的一个 Master Node 上,这三个进程包括:
Node 是一台虚拟机或物理电脑,在集群中作为 Worker。Master 管理 Cluster,而 Node 则管理应用。
每个 Node 都有一个 Kubelet,是管理 Node 的媒介,且负责与 Kubernetes Master 进行交互。
每个 Node 还需要有工具来处理容器操作,比如 Docker 或 rkt。
一个生产环境的 cluster 必须由至少 3 个 Node 组成。
节点代理,负责和 Kubernetes Master 交互:
运行于每个 Node 上的一个网络代理,可以执行简单的 TCP、UDP、SCTP 流转发或提供多后端进程的负载均衡。
相当于在主机和 Cluster 之间创建了一个连接,让我们能直接访问 API。
一个或多个应用容器集合的抽象,并且包含一些共享资源,包括:
Pod 建模了一种“logical host”,可以同时运行多种不同的容器。
当 Pod 所处的 Node 挂了,ReplicaSet会动态地创建新 Pod 来使得 Cluster 回到原来的状态。
Service 定义了 Pod 的逻辑集合及其访问规则,虽然每个 Pod 都有一个唯一的 IP 地址(Cluster 范围内),但是如果没有 Service 的话这些 IP 也是没法暴露到 Cluster 外的,可以通过指定 ServiceSpec 中的type来指定暴露服务的方式:
<NodeIP>:<NodePort>. Superset of ClusterIP.externalName in the spec) by returning a CNAME record with the name. No proxy is used. This type requires v1.7 or higher of kube-dns.负责创建和更新应用实例,创建 Deployment 后,Master 会持续监听并在各 Node 中调度应用实例,一旦有实例挂掉或被删掉,Deployment controller 就会用 Cluster 中另一 Node 上的实例取代之。
可以采用kubectl命令来和 Cluster 交互,kubectl最常用的操作只有如下 4 种:
例子中使用minikube创建 Cluster,然后使用kubectl来和创建的 Cluster 交互:
1 | minikube version |
1 | # 创建Deploymnet |
1 | # 创建proxy实例 |
1 | # 所有应用发送给STDOUT的信息都会成为Pod容器的日志 |
1 | # 查看Pod内的环境变量 |
1 | # 查看Service |
1 | # 8080其实是集群内的一个逻辑端口,可以通过以下命令获取Node上暴露的端口 |
1 | # 先获取Pod的名字 |
1 | # 删除一个Service |
上图来自官网教程,Scaling 即修改 Deployment 中的 Pod 数。
1 | # 先看下部署了几个Pod |
1 | # 使用一个NODE_PORT环境变量来保存Node暴露的端口 |
1 | # 再运行一次scale命令来缩小ReplicaSet |
1 | # 先看看Cluster里有啥 |
1 | # 确认应用正在运行中 |
1 | # 设置镜像进行更新,但是这个镜像的v10版本是不存在的,因此会引起更新失败 |
在 awk、sed、cut 三个命令中,awk 是功能最强大的,基本能实现所有字符串操作,平时常用于较复杂的日志分析,不过比起别的命令来也会相对复杂一点。