Skip to content Skip to main navigation Skip to footer

Uncategorized

5种Linux下安全删除文件的软件工具(最新)

本文主要讲述Linux系统下5种不同的安全删除文件工具的用法介绍。 通常情况下,我们在Linux系统下删除文件的主要方法是通过rm命令或者unlink命令进行删除。 但是正如我们之前介绍过的rm命令删除文件的原理,该命令只是将文件所对应的inode链接删除,但是文件在磁盘存储的数据依然还在,这样就有可能造成数据的泄露。 下面我们会介绍5种Linux系统下永久安全的从磁盘中删除文件数据的工具。

Shred 删除工具

Shred工具主要是通过多次的覆盖文件的方式来达到安全删除文件的目的。
Shred 工具用法及选项
用法如下:

Shred [选项]  文件名

选项如下:

-f, --force           必要时修改权限以使目标可写
-n, --iterations=N    覆盖N 次,而非使用默认的3 次
--random-source=文件      从指定文件中取出随机字节
-s, --size=N          粉碎数据为指定字节的碎片(可使用K、M 和G 作为单位)
-u             truncate and remove file after overwriting
--remove[=HOW]  like -u but give control on HOW to delete;  See below
-v, --verbose  show progress
-x, --exact    do not round file sizes up to the next full block;
this is the default for non-regular files
-z, --zero     add a final overwrite with zeros to hide shredding
--help            显示此帮助信息并退出
--version         显示版本信息并退出

实例:删除当前目录下的文件fio.txt, 执行下面的命令:

# shred -zvu -n 3 fio.txt

命令输出如下:

root@devops:~/osetc# shred -zvu -n 3 fio.txt
shred: fio.txt:正在删除
shred: fio.txt:名称已更改为 0000000
shred: 0000000:名称已更改为 000000
shred: 000000:名称已更改为 00000
shred: 00000:名称已更改为 0000
shred: 0000:名称已更改为 000
shred: 000:名称已更改为 00
shred: 00:名称已更改为 0
shred: fio.txt:已删除

Wipe删除工具

接下来要介绍的第二种安全删除文件的工具是wipe, 该工具可以安全的删除指定磁盘上的文件,当文件被删除后,是无法再恢复的。
安装wipe工具
执行下面的命令:

#sudo apt-get install wipe

命令输出如下:

root@devops:~/osetc# apt-get install wipe
正在读取软件包列表... 完成
正在分析软件包的依赖关系树
正在读取状态信息... 完成
下列软件包是自动安装的并且现在不需要了:
java-common libappindicator1 libindicator7 Linux-headers-4.10.0-28
Linux-headers-4.10.0-28-generic Linux-image-4.10.0-28-generic
Linux-image-extra-4.10.0-28-generic
使用'apt autoremove'来卸载它(它们)。
下列【新】软件包将被安装:
wipe
升级了 0 个软件包,新安装了 1 个软件包,要卸载 0 个软件包,有 205 个软件包未被升级。
需要下载 41.8 kB 的归档。
解压缩后会消耗 128 kB 的额外空间。
获取:1 http://mirrors.aliyun.com/ubuntu xenial/universe amd64 wipe amd64 0.22-3 [41.8 kB]
已下载 41.8 kB,耗时 0秒 (268 kB/s)
正在选中未选择的软件包 wipe。
(正在读取数据库 ... 系统当前共安装有 290931 个文件和目录。)
正准备解包 .../archives/wipe_0.22-3_amd64.deb  ...
正在解包 wipe (0.22-3) ...
正在处理用于 man-db (2.7.5-1) 的触发器 ...
正在设置 wipe (0.22-3) ...

实例,安全删除当前目录下的文件fio.txt, 执行下面的命令:

wipe -rfi fio.txt

命令输出如下:

root@devops:~/osetc# wipe -rfi fio.txt
File fio.txt (0 bytes) wiped
Operation finished.
1 file wiped and 0 special files ignored in 0 directories, 0 symlinks removed but not followed, 0 errors occured.

Secure-delete删除文件工具

接下来要介绍的是一款名叫secure-delete的安全文件删除工具集合,该集合里包含用来安全删除指定文件的工具叫srm
安装secure-delete 工具集
执行下面的命令:

#sudo apt-get install secure-delete

命令输出如下

root@devops:~/osetc# sudo apt-get install secure-delete
sudo: 无法解析主机:devops
正在读取软件包列表... 完成
正在分析软件包的依赖关系树
正在读取状态信息... 完成
下列软件包是自动安装的并且现在不需要了:
java-common libappindicator1 libindicator7 Linux-headers-4.10.0-28
Linux-headers-4.10.0-28-generic Linux-image-4.10.0-28-generic
Linux-image-extra-4.10.0-28-generic
使用'sudo apt autoremove'来卸载它(它们)。
下列【新】软件包将被安装:
secure-delete
升级了 0 个软件包,新安装了 1 个软件包,要卸载 0 个软件包,有 205 个软件包未被升级。
需要下载 62.7 kB 的归档。
解压缩后会消耗 161 kB 的额外空间。
获取:1 http://mirrors.aliyun.com/ubuntu xenial/universe amd64 secure-delete amd64 3.1-6ubuntu1 [62.7 kB]
已下载 62.7 kB,耗时 0秒 (365 kB/s)
正在选中未选择的软件包 secure-delete。
(正在读取数据库 ... 系统当前共安装有 290943 个文件和目录。)
正准备解包 .../secure-delete_3.1-6ubuntu1_amd64.deb  ...
正在解包 secure-delete (3.1-6ubuntu1) ...
正在处理用于 man-db (2.7.5-1) 的触发器 ...
正在设置 secure-delete (3.1-6ubuntu1) ...

如果要删除当前目录下的fio.txt文件,可以执行下面的命令:

#srm –vz fio.txt

命令输出如下:

root@devops:~/osetc# srm -vz fio.txt
Using /dev/urandom for random input.
Wipe mode is secure (38 special passes)
Wiping fio.txt ************************************** Removed file fio.txt ... Done

Sfill 安全删除文件工具

Sfill工具是secure-delete工具集里的一个安全删除文件的另一个工具,该工具主要用来安全的删除磁盘上所有可用空间上的文件。主要针对通过rm命令删除文件的inode链接的那些空间上的文件。该工具会对磁盘进行检查,将找到的可用空间通过/dev/urandom 设备上的随机数据进行填充。
执行命令:

#sfill –v osetc

命令输出如下:

root@devops:~# sfill -v osetc/
Using /dev/urandom for random input.
Wipe mode is secure (38 special passes)
Wiping now ...
Creating osetc/oooooooo.ooo ...

Sdmem 删除内存数据工具

最后我们要介绍一种可以安全的删除RAM 内存储器中的数据的工具名叫sdmem
执行命令如下:

#sdmem –f –v

命令输出如下:

root@devops:~/osetc# sdmem -f -v
Starting Wiping the memory, press Control-C to abort earlier. Help: "sdmem -h"
Wipe mode is secure (38 special passes)

99%的人还阅读了:

CURL命令忽略https请求的SSL证书

在使用wget命令来获取文件的时候,我们可以使用wget命令的 –-no-check-certificate 选项来忽略证书的认证。 那么在执行curl命令是否也可以忽略SSL证书的警告信息呢。
当然是有的,我们可以在执行curl 命令的时候,使用 -k 或者 –insecure 选项,来忽略签名认证的警告。 这样就可以让curl命令执行不安全的SSL连接,进而去获取数据。
命令使用示例如下:
curl -k https://osetc.com
curl --insecure https://www.osetc.com
在php中我们通过curl来实现post 和get请求的时候,也可以忽略SSL证书的验证,大家可以参考下面的代码:
function request_by_curl($url, $post_data = '', $timeout = 30) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    //post提交,否则get
    if ($post_data != '') {
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    }
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
     curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
     curl_setopt($ch, CURLOPT_HEADER, false);
     //跳过SSL验证
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, '0');
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, '0');
    $file_contents = curl_exec($ch);
    curl_close($ch);
    return $file_contents;
}
函数调用如下:
//$result存储返回的数据
//post
$result = request_by_curl('http://www.xxx.com', 'username=admin&password=123');
//get
 $result = request_by_curl('http://www.xxx.com');

99%的人还阅读了:
Linux:用腻了 wget 或 curl,有什么更好的替代品吗?
Mac OS:终端下使用curl命令下载文件
Ubuntu 下curl安装及使用指南
Linux 下curl命令post传递表单数据

12 个最佳的免费网络监控工具

要让一个多级机构运行良好而且平稳的话,一个非常艰巨重大的任务就是做好网络管理。每个机构都配备专门的人员,即网络分析师,来进行网络管理。他们使用了许多工具来监视网络的运行状况,并查看网络流量的上升和下降状况。他们还必须确保整个网络能够平稳地运行,因为只要有一分钟的网络中断就会使得整个机构的工作出现混乱。
使得机构工作平稳运行的最重要的方式之一就是使用各种网络监视工具。使用IDS检测来自外部网络的威胁和问题,使用网络监视软件来监视由于内部服务器负载过高或者某个网络部员工的小错误而引起的问题。网络监视软件可以跟踪数据包的流向,而且它还可以对数据包活动表现异常的地方进行检测,以确定出错的地方。例如,为了检测web服务器的运行状况,网络监视软件将定期不间断地发送32位字节的ping请求,跟踪服务器是否收到了该请求并及时响应。
现有的网络监控工具可以说是数以百计,但是这些工具往往比较昂贵,因此花些时间去选购是很值得的,需要仔细研究其适用性、性能、专业性等方面的特性,需要判断的因素很多,但短时间内理解这些指标并作出选择可不是一件容易的事。因此,我们利用专业经验,建立了包括一些最佳免费网络监控工具的清单,为实现网络的安全、稳定长期运行提供帮助,以下是具体的清单列表:

1) Fiddler

Fiddler(几乎)是适用于任何平台和任何操作系统的最好的免费网络工具,并提供了一些广受欢迎的关键特性。如:性能测试、捕捉记录HTTP/HTTPs请求响应、进行web调试等很多功能.
Fiddler
2) Nagios
Nagios是另外一款在互联网上的免费网络监控工具。 它是开源的监控解决方案,它表现非凡并且持续为全球成千上万的组织提供可靠的监测。
Nagios

3) Nedi

Nedi也是一款对用户来说开源的网络监控工具。 NeDi可以在你的核心网络设备上,针对CDP, FDP和、或LLDP充分发挥潜力。它还可以包括其他网络组件, 当他们位于网络边界上,也可以工作地非常好。

4) EasyNetMonitor

一个监控你电脑本地和互联网主机之间网络的最小免费工具。开始我们的EasyNetMonitor,打开弹出菜单可以看到你电脑的网络状态信息。
免费网络监控 EasyNetMonitor 是一个小而简单易用的测试远程主机和其他网络主机之间网络到达率的工具。很简单的点击EasyNetMonitor图标就可以获得关于你本地网络和互联网主机的实时信息。

5) Microsoft Network Monitor

这个是Microsoft. Network Monitor 3.4稳定版非开发版协议分析器提供的网络监控工具。微软消息分析器替代了网络监控3.4。微软消息分析器提供最新的协议分析,比如捕捉屏幕,显示,协议消息流量分析、事件和在其他系统或应用程序消息故障排除和诊断方案方面。这是一个更强大的工具来捕获和分析协议消息。
Microsoft Network Monitor

6) Cacti

Cacti 是一个完整的网络绘图解决方案旨在利用RRDTool的数据存储和图形绘制功能。Cacti提供了一个快速的轮询器,先进的图形模板,多个数据采集方法和用户管理的开箱即用的特性。所有的封装都是为局域网内的数百台设备复杂网络的安装提供很直观的,易用的界面。
Cacti

7) Zenoss

Zenoss 的核心是为企业IT监控工具提供一些关键特性-

  • 跨平台设备性能和可用性监控
  • 高度可定制的基于web的控制台和仪表板
  • 设备探索、建模和分类
  • 三层网络拓扑图
  • 最好的数据收集
  • 错误和事件监控和管理
  • 事件分类、重复数据删除、自动清档、映射转换,和生命周期管理
  • 事件触发和通知
  • 可用性监控设备、网络、进程和服务等

8) Paessler

Paessler是一个强大的易用的网络监控软件。PRTG网络监视器运行在Windows机器的网络上,可以收集你指定的机器,软件和设备的各种统计数据。PRTG附带一个易于使用的web界面点击配置。你可以很容易地共享数据给非技术的同事和客户,包括通过现场图和自定义报告。
Paessler

9) Bandwidthd

BandwidthD可以跟踪使用TCP / IP网络的子网和构建html文件图表显示的利用率。
Bandwidthd

10) Icinga

Icinga是一个处理多服务,多设备以及它们之间复杂依赖关系的网络监控工具。不需要进行复杂的安装或维护监测系统。

11) The Dude

The Dude 网络监控是由 MikroTik 提供的新的应用程序,可以大大提高你的管理您的网络环境。它会自动扫描指定的子网内的所有设备,绘制地图和布局你的网络,监控服务的设备和提醒你,以防一些服务问题。
The Dude

12) Total Network Monitor

Total Network Monitor 是一个为持续监控本地网络,个人电脑以及需要细心观察和深入控制的服务提供的免费网络监控软件。
Total Network Monitor
参考:http://os.51cto.com/art/201502/464662.htm
 

RHCSA 系列(三): 如何管理 RHEL7 的用户和组

和管理其它Linux服务器一样,管理一个 RHEL 7 服务器要求你能够添加、修改、暂停或删除用户帐户,并且授予他们执行其分配的任务所需的文件、目录、其它系统资源所必要的权限。

User and Group Management in Linux

RHCSA: 用户和组管理 – Part 3

管理用户帐户

如果想要给RHEL 7 服务器添加账户,你需要以root用户执行如下两条命令之一:

# adduser [new_account]
# useradd [new_account]

当添加新的用户帐户时,默认会执行下列操作。

  • 它/她的主目录就会被创建(一般是”/home/用户名”,除非你特别设置)
  • 一些隐藏文件 如.bash_logout, .bash_profile 以及 .bashrc 会被复制到用户的主目录,它们会为用户的回话提供环境变量。你可以进一步查看它们的相关细节。
  • 会为您的账号添加一个邮件池目录。
  • 会创建一个和用户名同样的组(LCTT 译注:除非你给新创建的用户指定了组)。

用户帐户的全部信息被保存在/etc/passwd文件。这个文件以如下格式保存了每一个系统帐户的所有信息(字段以“:”分割)

[username]:[x]:[UID]:[GID]:[Comment]:[Home directory]:[Default shell]
  • [username][Comment] 其意自明,就是用户名和备注
  • 第二个‘x’表示帐户的启用了密码保护(记录在/etc/shadow文件),密码用于登录[username]
  • [UID][GID]是整数,它们表明了[username]的用户ID 和所属的主组ID

最后。

  • [Home directory]显示[username]的主目录的绝对路径
  • [Default shell] 是当用户登录系统后使用的默认shell

另外一个你必须要熟悉的重要的文件是存储组信息的/etc/group。和/etc/passwd类似,也是每行一个记录,字段由“:”分割

[Group name]:[Group password]:[GID]:[Group members]
  • [Group name] 是组名
  • 这个组是否使用了密码 (如果是”x”意味着没有)
  • [GID]: 和/etc/passwd中一样
  • [Group members]:用户列表,使用“,”隔开。里面包含组内的所有用户

添加过帐户后,任何时候你都可以通过 usermod 命令来修改用户账户信息,基本的语法如下:

# usermod [options] [username]

相关阅读

示例1 : 设置帐户的过期时间

如果你的公司有一些短期使用的帐户或者你要在有限时间内授予访问,你可以使用 –expiredate 参数 ,后加YYYY-MM-DD 格式的日期。为了查看是否生效,你可以使用如下命令查看

# chage -l [username]

帐户更新前后的变动如下图所示

Change User Account Information

修改用户信息

示例 2: 向组内追加用户

除了创建用户时的主用户组,一个用户还能被添加到别的组。你需要使用 -aG或 -append -group 选项,后跟逗号分隔的组名。

示例 3: 修改用户主目录或默认Shell

如果因为一些原因,你需要修改默认的用户主目录(一般为 /home/用户名),你需要使用 -d 或 -home 参数,后跟绝对路径来修改主目录。

如果有用户想要使用其它的shell来取代默认的bash(比如zsh)。使用 usermod ,并使用 -shell 的参数,后加新的shell的路径。

示例 4: 展示组内的用户

当把用户添加到组中后,你可以使用如下命令验证属于哪一个组

# groups [username]
# id [username]

下面图片的演示了示例2到示例4

Adding User to Supplementary Group

添加用户到额外的组

在上面的示例中:

# usermod --append --groups gacanepa,users --home /tmp --shell /bin/sh tecmint

如果想要从组内删除用户,取消 –append 选项,并使用 –groups 和你要用户属于的组的列表。

示例 5: 通过锁定密码来停用帐户

如果想要关闭帐户,你可以使用 -l(小写的L)或 -lock 选项来锁定用户的密码。这将会阻止用户登录。

示例 6: 解锁密码

当你想要重新启用帐户让它可以继续登录时,使用 -u 或 –unlock 选项来解锁用户的密码,就像示例5 介绍的那样

# usermod --unlock tecmint

下面的图片展示了示例5和示例6:

Lock Unlock User Account

锁定上锁用户

示例 7:删除组和用户

如果要删除一个组,你需要使用 groupdel ,如果需要删除用户 你需要使用 userdel (添加 -r 可以删除主目录和邮件池的内容)。

# groupdel [group_name]        # 删除组
# userdel -r [user_name]       # 删除用户,并删除主目录和邮件池

如果一些文件属于该组,删除组时它们不会也被删除。但是组拥有者的名字将会被设置为删除掉的组的GID。

列举,设置,并且修改标准 ugo/rwx 权限

著名的 ls 命令 是管理员最好的助手. 当我们使用 -l 参数, 这个工具允许您以长格式(或详细格式)查看一个目录中的内容。

而且,该命令还可以用于单个文件中。无论哪种方式,在“ls”输出中的前10个字符表示每个文件的属性。

这10个字符序列的第一个字符用于表示文件类型:

  • – (连字符): 一个标准文件
  • d: 一个目录
  • l: 一个符号链接
  • c: 字符设备(将数据作为字节流,例如终端)
  • b: 块设备(以块的方式处理数据,例如存储设备)

文件属性的接下来的九个字符,分为三个组,被称为文件模式,并注明读(r)、写(w)、和执行(x)权限授予文件的所有者、文件的所有组、和其它的用户(通常被称为“世界”)。

同文件上的读取权限允许文件被打开和读取一样,如果目录同时有执行权限时,就允许其目录内容被列出。此外,如果一个文件有执行权限,就允许它作为一个程序运行。

文件权限是通过chmod命令改变的,它的基本语法如下:

# chmod [new_mode] file

new_mode 是一个八进制数或表达式,用于指定新的权限。随意试试各种权限看看是什么效果。或者您已经有了一个更好的方式来设置文件的权限,你也可以用你自己的方式自由地试试。

八进制数可以基于二进制等价计算,可以从所需的文件权限的文件的所有者、所有组、和世界组合成。每种权限都等于2的幂(R = 2^2,W = 2^1,x = 2^0),没有时即为0。例如:

File Permissions

文件权限

在八进制形式下设置文件的权限,如上图所示

# chmod 744 myfile

请用马上来对比一下我们以前的计算,在更改文件的权限后,我们的实际输出为:

Long List Format

长列表格式

示例 8: 寻找777权限的文件

出于安全考虑,你应该确保在正常情况下,尽可能避免777权限(任何人可读、可写、可执行的文件)。虽然我们会在以后的教程中教你如何更有效地找到您的系统的具有特定权限的全部文件,你现在仍可以组合使用ls 和 grep来获取这种信息。

在下面的例子,我们会寻找 /etc 目录下的777权限文件。注意,我们要使用第二章:文件和目录管理中讲到的管道的知识:

# ls -l /etc | grep rwxrwxrwx

Find All Files with 777 Permission

查找所有777权限的文件

示例 9: 为所有用户指定特定权限

shell脚本,以及一些二进制文件,所有用户都应该有权访问(不只是其相应的所有者和组),应该有相应的执行权限(我们会讨论特殊情况下的问题):

# chmod a+x script.sh

注意: 我们可以使用表达式设置文件模式,表示用户权限的字母如“u”,组所有者权限的字母“g”,其余的为“o” ,同时具有所有权限为“a”。权限可以通过+ 来授予和收回。

Set Execute Permission on File

为文件设置执行权限

长目录列表还用两列显示了该文件的所有者和所有组。此功能可作为系统中文件的第一级访问控制方法:

Check File Owner and Group

检查文件的所有者和所有组

改变文件的所有者,您应该使用chown命令。请注意,您可以在同时或分别更改文件的所有组:

# chown user:group file

你可以更改用户或组,或在同时更改两个属性,但是不要忘记冒号区分,如果你想要更新其它属性,让另外的部分为空:

# chown :group file              # 仅改变所有组
# chown user: file               # 仅改变所有者

示例 10:从一个文件复制权限到另一个文件

如果你想“克隆”一个文件的所有权到另一个,你可以这样做,使用–reference参数,如下:

# chown --reference=ref_file file

ref_file的所有信息会复制给 file

Clone File Ownership

复制文件属主信息

设置 SETGID 协作目录

假如你需要授予在一个特定的目录中拥有访问所有的文件的权限给一个特定的用户组,你有可能需要使用给目录设置setgid的方法。当setgid设置后,该真实用户的有效GID会变成属主的GID。

因此,任何访问该文件的用户会被授予该文件的属组的权限。此外,当setgid设置在一个目录中,新创建的文件继承组该目录的组,而且新创建的子目录也将继承父目录的setgid权限。

# chmod g+s [filename]

要以八进制形式设置 setgid,需要在基本权限前缀以2。

# chmod 2755 [directory]

总结

扎实的用户和组管理知识,以及标准和特殊的 Linux权限管理,通过实践,可以帮你快速解决 RHEL 7 服务器的文件权限问题。

我向你保证,当你按照本文所概述的步骤和使用系统文档(在本系列的第一章 回顾基础命令及系统文档中讲到), 你将掌握基本的系统管理的能力。

请随时使用下面的评论框让我们知道你是否有任何问题或意见。


via: http://www.tecmint.com/rhcsa-exam-manage-users-and-groups/

作者:Gabriel Cánepa 译者:xiqingongzi 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

如何用 Bash 创建一个二进制发布包

linux下安装JDK的时候,Sun公司为JDK6的linux版本提供了一个shell的安装包,用起来特别的好用,基本上和在Windows下安装软件没什么两样,shell文件执行之后,几乎一切都系都设置好了,不用我们自己再动手设置PATH和JAVA_HOME,可是一个shell文件中是如何把二进制代码包含进来的呢?

再例如淘宝为linux开发的淘宝插件,其实也是一个shell文件,但是执行这个shell文件之后,会安装很多二进制的东西,同样的问题,Shell只是文本文件,其中的二进制是怎么来包含进来的呢?

从文本文件转换出可执行文件,通过编译器把源程序编程成可执行程序当然是可以的,但是前面提到的哪两种情况都不是这样做的。原因有两个,第一对于大的项目来说,编译需要的时间比较长,环境比较复杂;第二,更加重要的是,这样做其实和从源代码编译程序没什么两样,对于不想让用户看到自己的源码的商业软件来说,这显然是不可取的。

我们看看一般的程序是如何发布他们的二进制包的。

一般的程序,无非是把二进制和必要的文档压缩到一个压缩文件中,然后通过README文档的解释程序的运行依赖什么样的假设,然后,你就可以把程序自行的移动到你想移动的地方去了。

很多时候,我们把程序放到任何地方都是可以运行的,但是程序可以运行,并不是说我们已经完成了程序的安装,举个例子来说,如果我们解压JDK的二进制包之后,直接把程序移动到一个地方,然后把对应的bin目录添加到PATH中就可以执行JDK提供的一系列工具了。

但是如果我们安装其他的依赖与JDK的程序的时候,比如TOMCAT,那么就会有问题。因为我们只是在PATH中加入了JDK的bin目录而没有制定JAVA_HOME这个环境变量,所以TOMCAT很可能会不能运行。

再比如我们使用man命令来查看一个程序的手册,一般情况下二进制包中也会包含man文档的,但是如果我们只是把解压的二进制包的路径添加到了PATH中,还不能在man中找到对应的文档。

也正是因为这样的原因吧,所以很多的二进制包的发布是使用deb或者rpm包来发布。安装的时候少了很多的烦恼。要制做deb或者rpm包当然是需要学习成本的,而且deb和rpm也只能在对应的linux发行版中使用,如果想要为所有的Linux发行版都提供一个安装文件,那么使用shell文件来做无疑是最好的办法。

Shell的学习成本低,而且对linux平台来说有通用,那么是如何做到的呢?

想想我们在手动安装的情形,无非是把压缩的二进制包解压,移动到特定的目录下,在PATH变量中添加二进制包的可执行文件的路径等等工作。首先我们把二进制包压缩文件和shell文件分开。这样一来,shell中只要完成解压,然后把解压后的目录移动到指定的目录中去,设置各种各样的环境变量然后就完成了工作了。

但是我们在如何把压缩文件和这个shell解压之后要执行的命令的shell文件一起放到一个shell文件中呢?

要做到这一点,首先这个shell文件中,要有可以解压的二进制内容,其次,这个shell要做的工作就是,把二进制内容,解压,然后把原来手动做的工作在这个shell中用命令完成。再用shell写个脚本完成一些手动完成的工作,这个任务比较容易,所以制作shell安装包的难点就是如何在其中包含二进制内容了。

如何在一个文本文件中记录二进制的内容呢?

这个问题早就被解决了。答案就是使用Base64编码。在linux下就有base64 这个命令程序就是来做这个工作的。base64可以把文件进行base64的编码,输出的标准输出中去或者把文件中的Base64编码的内容解码。命令base64除了可以对文件的内容做Base64的编解码外,也可以对标准输入中的数据进行Base64编辑码。

有了这些预备的知识,那么我们就可以看看具体的如何来做shell的二进制发布包了。

首先假设我们要发布的文件都放在名为test的当前文档中。

  1. 把要发布的文件打包

    tar zcf test.tar ./test
  2. 对打好的二进制包做Base64编码

    base64 ./test.tar > test_base64.txt
  3. 准备安装文件的shell文件

    test_base64="";#test_base64中的所有内容
    echo $test_base64|base64 -d >test.tar
    tar zxf test.tar
    rm test.tar
    # 其他的安装代码

写到这里,我们已经把道理将明白了。但是可不可以写一个shell程序,专门来生成这样的发布包软件呢?当然可以。下面是我写的这个打包程序的源代码。

function mkpackage(){
    target_dir=$1
    felow_install_shell_command_file=$2
    echo "tar -zcf ._test_dir.tar.gz $target_dir"
    tar -zcf ._test_dir.tar.gz $target_dir
    base64 ._test_dir.tar.gz >._base64
    rm ._test_dir.tar.gz
    printf "test_base64=\"">install.sh
    while IFS='' read -r line || [[ -n "$line" ]]; do
    printf "$line\\" >>install.sh
    printf "n" >>install.sh
    done <./._base64
    rm ._base64
    echo "\"" >>install.sh
    echo 'printf $test_base64|base64 -d >._temp.tar.gz;'>>install.sh
    echo 'tar zxf ._temp.tar.gz' >> install.sh
    echo 'rm ._temp.tar.gz' >>install.sh
    if [[ -e $fellow_install_shell_command_file ]]; then
        cat $fellow_install_shell_command_file >>install.sh
    fi
    chmod +x install.sh
}
function usage(){
   echo "usage:"
   echo "    $1 test_dir [the_command.sh]"
}
if [[ $# != 0 ]]
then
    mkpackage $1 $2
else
   usage $0
fi

这个程序接受两个输入参数,第一个表示要打的程序包目录,第二个是解压后,安装动作的shell脚本文件。最后这个程序生成一个名为 install.sh 的文件。执行 install.sh 之后,会首先得到加压的程序包内容,然后执行第二个参数指定的 shell 脚本的内容。这样我们就做了用Shell发布二进制文件的一个打包程序。当然了,在最后发布之前,还需要把这个shell压缩一下。以便消除因为Base64编码而带来的文件长度的变大的影响。

PHP 之 FastCGI 与 mod_php 详解

网上对于FastCGI与mod_php的知识比较杂乱而不全面,故在此整理一下,以便入门学习者查阅方便。

背景

PHP最常用的方式是以模块的方式(mod_php)运行在Apache中,也是Apache运行PHP的默认方式;但在Nginx中,Nginx又使用的是PHP-FPM,但是PHP-FPM到底是个什么东东?跟php有什么关系?今天我们一起来探究一番。

PHP处理器(PHP handlers)

首先需要记住的是,任何一种Web服务器(Apache、Nginx等)都是被设计成向用户发送html、图片等静态资源的,Web服务器自身并不能解释任何动态脚本(PHP、Python等)。

PHP处理器就是用来解释Web应用中的PHP代码,并将它解释为HTML或其他静态资源,然后将解析的结果传给Web服务器,最后再由Web服务器发送给用户。

大多数的Web服务器都不能解析PHP代码,因此它需要一个能解析PHP代码的程序,这就是PHP处理器。

现在我们知道了,Apache与Nginx都需要PHP处理器来处理php代码,那么怎么连接上服务器与php处理器呢?也就是说服务器与php处理器如何通信?

答案是通过SAPI(Server Application Programming Interface 服务器端应用编程端口),简单来说,SAPI指的是PHP具体应用的编程接口, 就像PC一样,无论安装哪些操作系统,只要满足了PC的接口规范都可以在PC上正常运行, PHP脚本要执行有很多种方式,通过Web服务器,或者直接在命令行下,也可以嵌入在其他程序中,有兴趣大家可以研究PHP内核。

我们这里继续讨论PHP最常用的SAPI提供的2种连接方法:mod_php和mod_fastcgi。

mod_php模式

咱们回顾一下,Apache是怎么能够识别php代码的?是不是Apache的配置文件httpd.conf中加上或者修改这样几句:

//添加
LoadModule php5_module modules/libphp5.so
AddType application/x-httpd-php .php
//修改

DirectoryIndex index.php index.html index.htm index.html

也即php作为Apache的一个子模块来运行,当通过web访问php文件时,Apache就会调用php5_module来解析php代码。

配置加载mod_php模块后,php便是Apahce进程本身一部分,每个新的Apache子进程都会加载此模块。

mod_fastcgi模式

我们先看PHP-FPM官网的说明:

PHP-FPM – A simple and robust FastCGI Process Manager for PHPPHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation with some additional features useful for sites of any size, especially busier sites.

PHP-FPM是一个PHP的FastCGI进程管理器,解释的非常简单。这说明PHP-FPM是辅助mod_fastcgi模式进行工作的,然而FastCGI又是个什么东西?管理着什么进程?

什么是CGI?

CGI(Common Gateway Interface) 是WWW技术中最重要的技术之一,有着不可替代的重要地位。

CGI是外部应用程序(CGI程序)与Web服务器之间的接口标准,是在CGI程序和Web服务器之间传递信息的规程。

CGI规范允许Web服务器执行外部程序,并将它们的输出发送给Web浏览器,CGI将Web的一组简单的静态超媒体文档变成一个完整的新的交互式媒体。

说白了,CGI是一种外部应用程序(CGI程序)与Web服务器的协议,CGI是为了保证Server传递过来的数据是标准格式。

什么是FastCGI?

FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute 模式)。它还支持分布式的运算, 即 FastCGI 程序可以在网站服务器以外的主机上执行并且接受来自其它网站服务器来的请求。

FastCGI是语言无关的、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并因此获得较高的性能。众所周知,CGI解释器的反复加载是CGI性能低下的主要原因,如果CGI解释器保持在内存中并接受FastCGI进程管理器调度,则可以提供良好的性能、伸缩性、Fail- Over特性等等。

一般情况下,FastCGI的整个工作流程是这样的:

  1. Web Server启动时载入FastCGI进程管理器(IIS ISAPI或Apache Module)。
  2. FastCGI进程管理器自身初始化,启动多个CGI解释器进程(可见多个php-cgi)并等待WebServer的连接。
  3. 当客户端请求到达Web Server时,FastCGI进程管理器选择并连接到一个CGI解释器。 Web server将CGI环境变量和标准输入发送到FastCGI子进程php-cgi。
  4. FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时,请求便告处理完成,FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在Web Server中)的下一个连接,在CGI模式中,php-cgi在此便已经退出。

也就是说FastCGI是CGI的升级版,一种语言无关的协议,用来沟通程序(如PHP, Python, Java)和Web服务器(Apache2, Nginx), 理论上任何语言编写的程序都可以通过FastCGI来提供Web服务。

FastCGI的特点是会在一个进程中依次完成多个请求,以达到提高效率的目的,大多数FastCGI实现都会维护一个进程池。

通俗解释:FastCGI事先就需要启动,而且可以启动多个CGI模块,在那里一直运行等着web发请求,然后再给php解析运算,完成后生成html返回给web后,但是完成后它不会退出,而是继续等着下一个web请求。

PHP-FPM

PHP-FPM就是针对于PHP的FastCGI的一种实现,他负责管理一个进程池,来处理来自Web服务器的请求。

但是PHP-FPM仅仅是个“PHP FastCGI 进程管理器”, 它仍会调用PHP解释器本身来处理请求,PHP解释器(在Windows下)就是php-cgi.exe。

结束语

说了这么多,也不知道是否表达清楚,如果有不正确的地方请指正,谢谢。

Zorin OS:Linux新手最应该使用的个人桌面系统

Zorin OS 是一款基于 Ubuntu 的 Linux 发行版,特别为 Linux 新手而设计。它拥有类似 Windows 的图形用户界面,以及很多类似 Windows 下的应用软件。Zorin OS 还带有能让用户运行很多Windows 软件的程序。该发行版的终极目标是提供一份可作为 Windows 替换的 Linux 选择,并让 Windows 用户在避免烦琐的同时享受 Linux 的所有特性。

这一段话是几乎所有的中国的 Linux 网站上对 Zorin OS 的描述。

本人是 linux 新手,在 Linux 中国的新手群里得到各位大神的指点,安装了很多适合个人用的 linux 桌面系统(Ubuntu/fedora/麒麟,还有一些非常用的小众 linux 桌面系统),说实话,被折腾的够呛,主要原因是安装网卡驱动、显卡驱动、影音解码软件,然后出现各种问题,导致无法安心下来学习 linux 系统的相关知识和操作。无意之中看到 Zorin OS 的相关介绍,介绍比较动心,于是去官方下载了 Zorin OS 10 Ultimate(64位)版(官方下载地址:http://zorinos.com/download.html)。在虚拟机进行了安装,安装后感觉该系统的确适合我们新手使用,同时安装简单,安装后的系统各种程序齐全,功能强大。

具体步骤和情况如下:

安装Zorin OS 10 Ultimate(64位),需要10G左右的空间,建议分区15-20G左右,内存我虚拟机设定为1G。

安装过程

安装还是试用

安装类型

选择键盘布局

设置用户和密码

正在复制文件

安装完成后会进行必要的更新。

更新完成后会下载语言包(因为我选择的是中文安装)。

下载语言包

语言包安装完成后会进行硬件检测和硬件驱动安装。然后提示你重新启动,点击重新启动即可。

使用 Ansible 高效交付 Docker 容器

使用 playbook、插件和 Docker 模块设置和扩展 Ansible 环境

Docker 和它的容器工作流可封装、共享和部署您的应用程序环境。Ansible 是一个与 Docker 高度兼容的自动化工具,它使用一个强大的接口来管理远程服务器上的容器。在本文中,我将探索为何和如何使用 Ansible 的可扩展设计来将 Docker 和 Ansible 的最佳功能合并在一起。

Docker 之所以如此流行,是因为它创造了一种采用方便的命令行接口 (CLI) 和 HTTP API 工具来封装、运行和维护容器的独特方式。这种简化降低了此技术的入门门槛,使得将应用程序及其运行时环境封装到一个简单 Dockerfile 中的独立镜像中变得可行。Docker 使您能够开发更复杂的项目,但您仍需要配置这些容器。在本文中,我将展示 Ansible 如何通过更清晰的语法带来配置管理器的特性。您将学习如何仅使用已安装的 Python 和 Docker 构建任何堆栈。

在介绍 Ansible 的细节之前,我首先将介绍 Ansible 的 分析 中提到的一些要点:

  • 尽管容器导致一些新工作流出现,但编排和配置工具仍然非常活跃。
  • Ansible 和 Salt 等新参与者正在挑战现有的工具,比如 Chef 和 Puppet。
  • 许多与 Docker 有关联的开发人员也很关心这些工具。

更确切地讲,借助 Docker,您可以在几秒内实现完全隔离的堆栈环境,或者在服务器之间复制准确的设置。但是,Docker 不包含提供端到端体验的可靠工具,无论是针对开发还是生产。Docker 团队通过新的集群工具解决了这些不断演变的挑战,尝试将 Docker 转变为一个大规模运行容器的可靠解决方案。然而,Docker 仍然需要您手动硬编码任务和重复常见的设置。所以,针对容器的编排和配置管理的关键 Docker 流程仍有待解决。在本文中,您将学习如何结合使用 Ansible 和 Docker 来帮助解决这些问题。

DevOps 的兴起

在部署到生产中之前,现代应用程序通常涉及到一个复杂的部署管道。最佳实践建议在每次小型迭代后尽早地、频繁地发布代码。任务的手动执行无法扩展,组织已开始完善介于开发人员与系统管理员之间的流程,所以 DevOps 就诞生了。从那时起,敏捷团队就开始尝试强化和自动化测试代码,以及将其交付给用户的方式。

通过实现最新的技术和方法,公司对其服务器上的代码建立了信心。然而,随着应用程序在规模和复杂性上不断增长,开发人员和系统管理员继续面临着无数挑战。现在比以往更需要为产品提供受支持的社区驱动工具。

Ansible 的可扩展设计

在此环境中,Ansible 提供了一个有趣的框架来管理基础架构。您可以获得服务器定义的控制权,比如要安装的包或要复制的文件,并将该配置扩展到数千个服务器。Ansible playbook 构成了集群的目标状态的一种安全表示。它的 YAML 语法和庞大的模块列表生成了任何开发人员都能快速理解的易读性配置文件。不同于 Chef 或 Puppet,Ansible 是无代理的,这意味着您要在远程主机上运行命令,只需一个 SSH 连接即可。可以看到,Ansible 可轻松地处理 DevOps 复杂性。

但是,Ansible 是在容器快速兴起和它们在云开发环境中带来革命之前设计的。那么 Ansible 是否仍然有用?微型服务的范式和复杂开发环境引入了新的需求:

  • 轻量型镜像。为了容易传输或节省成本,镜像被剥离到仅剩下最低限度的依赖项。
  • 单一用途,单一流程。如果应用程序不是非常需要 SSH 守护进程,则无需运行它。
  • 短暂性。容器随时可能死亡、转移和复活。

在此上下文中,Ansible 的可扩展架构解决了这些问题。一个 Docker 模块在较高层面上管理主机和容器。尽管您可能会争论哪个编排工具(来自 Google 的 Kubernetes,还是来自 New Relic 的 Centurion)最适合此环境,但 Docker 模块执行效率很高,这正是我在本文中使用它的原因。但是,您还可以构建从其官方 Ansible 镜像启动的容器,然后在本地模式下从内部运行 playbook。尽管此方法非常适合 Packer,而且肯定也适合许多使用情况,但它的缺点通常极为关键。

  • 您被锁定在一个基础镜像中,无法再利用特殊的秘诀或其他堆栈。
  • 最终的工件已安装 Ansible 和它的依赖项,它们与实际应用程序毫无关系,这让工件变得更笨重。
  • 尽管 Ansible 可管理数千个服务器,但它只配备(Provision)了一个容器。

此方法将容器视为小型 VM,您可以在其中使用一个特定的解决方案。幸运的是,Ansible 拥有模块化设计。模块分散在不同的存储库中,而且 Ansible 的大部分功能都可以通过插件进行扩展。

在下一节中,您将设置一个有效的环境,针对您的需求来调整 Ansible。

设置一个 Ansible 环境

假设您想要一个很容易部署的工具,它在轻量型容器中配置应用程序环境。由于与这些容器分离,您需要一个安装了 Ansible 的客户端,您将使用它来向 Docker 守护进程发送命令。此设置如 图 1 中所示。

图 1. 使用 Ansible 配备容器所需的组件

您在此配置中必须管理的依赖项,已通过从容器中运行 Ansible 来最小化。此架构将主机限制为容器与命令之间的一个通信桥梁。

可通过许多选项在您服务器上安装 Docker:

  • 使用 docker-machine 将它安装在远程主机上。
  • 安装在本地。顺便说一下,您可能不想亲自管理一个严格基于容器的基础架构;在这种情况下,可以考虑采用外部提供程序。
  • 依赖于外部提供程序。
  • 使用 boot2docker,这是一个在 Windows 和 Mac 上运行 Docker 容器的轻量型 Linux 发行版。

无论选择何种解决方案,请确保部署了 Docker 1.3 版或更高版本(1.3 版引入了进程注入)。您还需要运行一个 SSH 服务器来安全地处理 Ansible 命令。

以下的命令使用公钥设置了一种方便可靠的身份验证方法。

# install dependencies
sudo apt-get install -y openssh-server libssl-dev
# generate private and public keys
ssh-keygen -t rsa -f ansible_id_rsa
# allow future client with this public key to connect to this server
cat ansible_id_rsa.pub >> ~/.ssh/authorized_keys
# setup proper permissions
chmod 0700  ~/.ssh/
chmod 0600  ~/.ssh/authorized_keys
# make sure the daemon is running
sudo service ssh restart

配置 SSH 和安全性问题不属于本文的讨论范围。细心的读者可查阅 /etc/ssh/sshd_config 文件,进一步了解配置 SSH 的可用选项。

下一步是将公钥加载到运行 Ansible 的客户端容器上并配备构建器容器。使用一个 Dockerfile 来配备构建器。参见以下代码。

配备构建器的 Dockerfile:

FROM python:2.7
# Install Ansible from source (master)
RUN apt-get -y update && \
    apt-get install -y python-httplib2 python-keyczar python-setuptools python-pkg-resources
git python-pip && \
    apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN pip install paramiko jinja2 PyYAML setuptools pycrypto>=2.6 six \
    requests docker-py  # docker inventory plugin
RUN git clone http://github.com/ansible/ansible.git /opt/ansible && \
    cd /opt/ansible && \
    git reset --hard fbec8bfb90df1d2e8a0a4df7ac1d9879ca8f4dde && \
    git submodule update --init
ENV PATH /opt/ansible/bin:$PATH
ENV PYTHONPATH $PYTHONPATH:/opt/ansible/lib
ENV ANSIBLE_LIBRARY /opt/ansible/library
# setup ssh
RUN mkdir /root/.ssh
ADD ansible_id_rsa /root/.ssh/id_rsa
ADD ansible_id_rsa.pub /root/.ssh/id_rsa.pub
# extend Ansible
# use an inventory directory for multiple inventories support
RUN mkdir -p /etc/ansible/inventory && \
    cp /opt/ansible/plugins/inventory/docker.py /etc/ansible/inventory/
ADD ansible.cfg  /etc/ansible/ansible.cfg
ADD hosts  /etc/ansible/inventory/hosts

这些指令改编自官方构建版本,自动化了一次来自 Ansible 主分支上的提交 fbec8bfb90df1d2e8a0a4df7ac1d9879ca8f4dde 有效安装。

主机和 ansible.cfg 配置文件已封装。通过使用容器,可以确保您将共享同一个环境。在本示例中,Dockerfile 安装了 Python 2.7.10 版和 Ansible 2.0.0。

主机配置文件:

# hosts
# this file is an inventory that Ansible is using to address remote servers.
Make sure to replace the information with your specific setup and variables
that you don't want to provide for every command.
[docker]
# host properties where docker daemon is running
192.168.0.12 ansible_ssh_user=xavier

Ansible 配置文件:

# ansible.cfg
[defaults]
# use the path created from the Dockerfile
inventory = /etc/ansible/inventory
# not really secure but convenient in non-interactive environment
host_key_checking = False
# free you from typing `--private-key` parameter
priva_key_file = ~/.sh/id_rsa
# tell Ansible where are the plugins to load
callback_plugins   = /opt/ansible-plugins/callbacks
connection_plugins = /opt/ansible-plugins/connections

在构建 Ansible 容器之前,您必须导出 DOCKER_HOST 环境变量,因为 Ansible 将使用它连接到远程 Docker 守护进程。在使用 HTTP 端点时,需要修改 /etc/default/docker

# make docker to listen on HTTP and default socket
DOCKER_OPTS="-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock"

输入命令 sudo service docker restart 来重新启动 Docker 守护进程,以便让对它的配置文件的更改生效。

以下命令将会构建并验证您用来输入命令的 Ansible 容器:

# you need DOCKER_HOST variable to point to a reachable docker daemon
# pick the method that suits your installation
# for boot2docker users
eval "$(boot2docker shellinit)"
# for docker-machine users, provisioning the running VM was named "dev"
eval "$(docker-machine env dev)"
# for users running daemon locally
export DOCKER_HOST=tcp://$(hostname -I | cut -d" " -f1):2375
# finally users relying on a remote daemon should provide the server's public ip
export DOCKER_HOST=tcp://1.2.3.4:2375
# build the container from Dockerfile
docker build -t article/ansible .
# provide server API version, as returned by `docker version | grep -i "server api"`
# it should be at least greater or equal than 1.8
export DOCKER_API_VERSION=1.19
# create and enter the workspace
docker run -it --name builder \
    # make docker client available inside
    -v /usr/bin/docker:/usr/bin/docker \
    -v /var/run/docker.sock:/var/run/docker.sock \
    # detect local ip
    -e DOCKER_HOST=$DOCKER_HOST \
    -e DEFAULT_DOCKER_API_VERSION=DOCKER_API_VERSION \
    -v $PWD:/app -w /app \  # mount the working space
    article/ansible bash
# challenge the setup
$ container > ansible docker -m ping
192.168.0.12 | SUCCESS => {
    "invocation": {
        "module_name": "ping",
        "module_args": {}
    },
    "changed": false,
    "ping": "pong"
}

目前为止,一切顺利。您能够从容器输入命令。在下一节中,将对 Ansible 使用特定于 Docker 的扩展。

使用 playbook 和插件扩展 Ansible 环境

实质上,Ansible 通过 playbook 自动化了它的执行,这些 playbook 是指定要执行的每个任务和它们的属性的 YAML 文件。

Ansible 还使用了清单 (inventory) 来将用户提供的主机映射到基础架构中的具体端点。不同于上一节中使用的静态 hosts 文件,Ansible 也支持动态内容。内置的列表包含一个 Docker 插件,该插件可查询 Docker 守护进程并向 Ansible playbook 共享大量信息。

# provision.yml
- name: debug docker host
  hosts: docker
  tasks:
  - name: debug infrastructure
    # access container data : print the state
    debug: var=hostvars["builder"]["docker_state"]
# you can target individual containers by name
- name: configure the container
  hosts: builder
  tasks:
   - name: run dummy command
     command: /bin/echo hello world

下面的命令查询 Docker 主机,导入事实,打印一些事实,并使用它们对构建器容器执行第二个任务(如上述所示)。

ansible-playbook provision.yml -i /etc/ansible/inventory
# ...
TASK [setup] ********************************************************************
fatal: [builder]: FAILED! => {"msg": "ERROR! SSH encountered an unknown error during the
connection. Re-run the command using -vvvv, which enables SSH debugging
output to help diagnose the issue", "failed": true}
# ...

Ansible 不能连接容器,因为它没有运行 SSH 服务器。SSH 服务器是一个要管理的额外进程,它与实际应用程序完全无关。在下一节中,我们将使用一个连接插件来排除此困难。

连接插件是实现传输命令(比如 SSH 或本地执行)的类。Docker 1.3 随带了 docker exec,并能够在容器命名空间内运行任务。此外,因为您之前已学习如何连接特定的目标容器,所以您可以使用此功能来处理 playbook。

像其他插件类型一样,连接挂钩继承一个抽象类,会在您将其放到预期的目录(您在配置文件 ansible.cfg 中定义的是/opt/ansible-plugins/connections)时自动可用。

# saved as ./connection_plugins/docker.py
import subprocess
from ansible.plugins.connections import ConnectionBase
class Connection(ConnectionBase):
   @property
    def transport(self):
        """ Distinguish connection plugin. """
        return 'docker'
   def _connect(self):
        """ Connect to the container. Nothing to do """
        return self
   def exec_command(self, cmd, tmp_path, sudo_user=None, sudoable=False,
                     executable='/bin/sh', in_data=None, su=None,
                     su_user=None):
        """ Run a command within container namespace. """
    if executable:
        local_cmd = ["docker", "exec", self._connection_info.remote_addr, executable, '-c', cmd]
    else:
        local_cmd = '%s exec "%s" %s' % ("docker", self._connection_info.remote_addr, cmd)
    self._display.vvv("EXEC %s" % (local_cmd), host=self._connection_info.remote_addr)
    p = subprocess.Popen(local_cmd,
        shell=isinstance(local_cmd, basestring),
        stdin=subprocess.PIPE, stdout=subprocess.PIPE,
        stderr=subprocess.PIPE)
    stdout, stderr = p.communicate()
    return (p.returncode, '', stdout, stderr)
    def put_file(self, in_path, out_path):
        """ Transfer a file from local to container """
        pass
    def fetch_file(self, in_path, out_path):
        """ Fetch a file from container to local. """
        pass
    def close(self):
        """ Terminate the connection. Nothing to do for Docker"""
        pass

此代码挂钩到 Ansible 模块中,以便通过一个本地 docker exec 而不是默认的 ssh 来运行命令。您需要重新排列一些设置步骤来告诉 Ansible 使用此插件。

# modify the builder Dockerfile to upload the plugin code
where Ansible is expecting connection plugins
echo "ADD connection_plugins/docker.py /opt/ansible-plugins/connections/docker.py" >> Dockerfile
# then, you need to explicitly tell which connection hook to use
when executing playbooks.
# you can achieve this by inserting the 'connection' property at the top
of provision tasks in provision.yml
- name: configure the container
  connection: docker
  hosts: builder
# you are ready to redeploy the builder container
# (providing DOCKER_HOST and DOCKER_API_VERSION are still set like before)
# rebuild the image
docker build -t article/ansible .
# restart the builder environment
docker run -it --name builder \
    # make docker client available inside
    -v /usr/bin/docker:/usr/bin/docker \
    -v /var/run/docker.sock:/var/run/docker.sock \
    # detect local ip
    -e DOCKER_HOST=$DOCKER_HOST \
    -e DEFAULT_DOCKER_API_VERSION=DOCKER_API_VERSION \
    -v $PWD:/app -w /app \  # mount the working space
    article/ansible bash
# rerun provisioning from inside
ansible-playbook -i /etc/ansible/inventory provision.yml
# ... Hurrah, full green output ...

目前为止,您在容器中运行 Ansible 任务,对容器或主机没有太多需求。尽管此实现满足了初始需求,但仍有一些不严密的地方需要解决。

前面的代码在同一个节点上运行任务。一种更逼真的工作流会启动一个新基础镜像,配置它,最终提交、推送和关闭得到的工件。得益于 Ansible 中内置的 Docker 模块,这些步骤无需额外的代码即可实现。

---
- name: initialize provisioning
  hosts: docker
  - name: start up target container
    docker:
      image: python:2.7
      name: lab
      pull: missing
      detach: yes
      tty: yes
      command: sleep infinity
      state: started
  # dynamically update inventory to make it available down the playbook
  - name: register new container hostname
    add_host: name=lab
- name: provision container
  connection: docker
  hosts: lab
  tasks:
      # ...
- name: finalize build
  hosts: docker
  tasks:
    - name: stop container
      docker:
        name: lab
        image: python:2.7
        state: stopped

前面已经提到过,自动命名和存储在成功配备后构建的镜像会很方便。不幸的是,Ansible 中的 Docker 模块没有实现方法来标记和推送镜像。您可以使用简单的 shell 命令来克服此限制。

# name the resulting artifact under a human readable image tag
docker tag lab article/lab:experimental
# push this image to the official docker hub
# make sure to replace 'article' by your own Docker Hub login (https://hub.docker.com)
# (this step is optional and will only make the image available from any docker host.
You can skip it or even use your own registry)
docker push article/lab:experimental

我们的工具正在成形,但它仍缺少一个必要特性:层缓存。

在使用 Dockerfile 构建容器时,通常需要迭代许多次才能完成。为了显著加快该过程,成功的步骤会被缓存并在后续运行中重用。

要复制此行为,我们的工具在每次成功完成任务后提交了容器状态。如果发生构建错误,该工具会从上次的快照位置重新启动配备过程。Ansible 承诺实现幂等的任务,所以以前成功的任务不会处理两次。

借助 Ansible,您可以使用回调插件来挂住任务事件。这些类应实现了特定的回调,这些回调在 playbook 生命周期的各个步骤上触发。

# save as callback_plugins/docker-cache.py
import hashlib
import os
import socket
# Hacky Fix `ImportError: cannot import name display`
# pylint: disable=unused-import
import ansible.utils
import requests
import docker
class DockerDriver(object):
    """ Provide snapshot feature through 'docker commit'. """
    def __init__(self, author='ansible'):
        self._author = author
        self._hostname = socket.gethostname()
        try:
            err = self._connect()
        except (requests.exceptions.ConnectionError, docker.errors.APIError), error:
            ansible.utils.warning('Failed to contact docker daemon: {}'.format(error))
            # deactivate the plugin on error
            self.disabled = True
            return
        self._container = self.target_container()
        self.disabled = True if self._container is None else False
    def _connect(self):
        # use the same environment variable as other docker plugins
        docker_host = os.getenv('DOCKER_HOST', 'unix:///var/run/docker.sock')
        # default version is current stable docker release (10/07/2015)
        # if provided, DOCKER_VERSION should match docker server api version
        docker_server_version = os.getenv('DOCKER_VERSION', '1.19')
        self._client = docker.Client(base_url=docker_host,
                                     version=docker_server_version)
        return self._client.ping()
    def target_container(self):
        """ Retrieve data on the container you want to provision. """
        def _match_container(metadatas):
            return metadatas['Id'][:len(self._hostname)] == self._hostname
        matchs = filter(_match_container, self._client.containers())
        return matchs[0] if len(matchs) == 1 else None
    def snapshot(self, host, task):
        tag = hashlib.md5(repr(task)).hexdigest()
        try:
            feedback = self._client.commit(container=self._container['Id'],
                                           repository='factory',
                                           tag=tag,
                                           author=self._author)
        except docker.errors.APIError, error:
            ansible.utils.warning('Failed to commit container: {}'.format(error))
            self.disabled = True
# pylint: disable=E1101
class CallbackModule(object):
    """Emulate docker cache.
    Commit the current container for each task.
    This plugin makes use of the following environment variables:
        - DOCKER_HOST (optional): How to reach docker daemon.
          Default: unix://var/run/docker.sock
        - DOCKER_VERSION (optional): Docker daemon version.
          Default: 1.19
        - DOCKER_AUTHOR (optional): Used when committing image. Default: Ansible
    Requires:
        - docker-py >= v0.5.3
    Resources:
        - http://docker-py.readthedocs.org/en/latest/api/
    """
    _current_task = None
    def playbook_on_setup(self):
        """ initialize client. """
        self.controller = DockerDriver(self.conf.get('author', 'ansible'))
    def playbook_on_task_start(self, name, is_conditional):
        self._current_task = name
    def runner_on_ok(self, host, res):
        if self._current_task is None:
            # No task performed yet, don't commit
            return
        self.controller.snapshot(host, self._current_task)

因为您已将代码上传到期望的位置,并重新构建了构建器容器,所以您可以像 docker exec 连接插件一样注册此插件。

# modify the builder Dockerfile to upload the code where Ansible is expecting callback plugins
echo "ADD callback_plugins/docker-cache.py /opt/ansible-plugins/callbacks/docker-cache.py" >> Dockerfile

重新构建构建器容器并重新运行 Ansible playbook 后,该模块会自动加载,您可以查看中间容器是如何创建的。

REPOSITORY          TAG                     IMAGE ID            CREATED             VIRTUAL SIZE
factory             bc0fb8843e88566c    bbdfab2bd904        32 seconds ago      829.8 MB
factory             d19d39e0f0e5c133    e82743310d8c        55 seconds ago      785.2 MB

结束语

配备是一个复杂流程,您在本教程中执行的实现为未来的开发奠定了基础。代码本身已经过简化,而且一些步骤仍需人类干预。缓存实现肯定值得更多关注,例如更具体的提交命名或清理技能。

尽管如此,您创建了一个可运行 Ansible playbook 来管理容器配置的工具。借助此实现,您可以通过为基础架构的微型服务来组合、重用和设置陈述性的构建文件,充分利用 Ansible 的全部威力。此解决方案可帮助避免锁定问题。您开发的插件包装了 playbook,您可对不同的目标重用这些 playbook,而且极低的需求使得该项目能兼容大部分提供程序。

Linux:MBR & GPT

MBR & GPT[转] 2011-04-25 08:57

MBR 和 GPT 的问题已经走到了非常现实的阶段-3T硬盘开始普及。MBR 由于对 3T 硬盘寻址无法支持,终于要开始被弃用了。但仅仅只是“开始”,我感觉至少10年之内 MBR 还不会消失。恐怕当GPT适应不了需求的时候,MBR才会消失。 一、MBR 的失误 说“失误”牵强了一点。我们不能要求当年只有5M的硬盘就扣出2M来放寻址信息。计算机永远比你想象的要发展的快。 首先你要有一些基本的硬盘的MBR知识,如果你不熟悉,可以先在 wiki 看一看硬盘的基本结构。 在了解了磁道、柱面、扇区之后,再看下面的 MBR 结构就很了然了:

基本MBR结构
偏移量(位置) (within sector) 长度 (in bytes) 解释
十进制 十六进制
000 – 445 000 – 1BD 446 引导程序
446 – 509 1BE – 1FD 64 分区表
510 – 511 1FE – 1FF 2 引导记录

表 1.

 

MBR 永远占用了第一个扇区,通常为512bytes大小。在这512bytes中被MBR本身的程序用去了446bytes。于是,真正描述分区信息的就只有 64 bytes。而根据4个主分区的设计,每一个分区能用到的只有 16bytes. 那么!这16bytes是如何工作的?

16-byte 分区表结构
Relative Offsets (within entry) 长度

(bytes)

内容
0 1 引导标记 (80h = active)
1 – 3 3 CHS 开始位置
4 1 分区类型描述
5 – 7 3 CHS 结束位置
8 – 11 4 启始扇区
12 – 15 4 分区大小 (扇区单位)

表 2.

 

在表2中,有2个“开始位置”,我们分开理解。 硬盘的历史过程中,第一个遇到的问题就是 8G 瓶颈。这就是因为在 CHS 描述方式中,描述起点和终点均为3个 byte。我们假设是 FF FF FF ,所以是 16*16*16*16*16*16*512=8589934592 这就是 8G 瓶颈的由来了。 但是今天 CHS 方式几乎已经不用了。后面还有 4 个 bytes 的“启始” 是给 LPA 方式用的。他的极限就是 8589934592 * 256 =2199023255552 这就是 2T 的限制由来了。 在硬盘容量的历史中,有很多因素决定了它的限制。BIOS,ATA(IDE),文件系统。百度上的这篇文章简单的介绍了各个阶段的限制。

二、GPT 的思路

GPT (GUID Partition Table)属于 EFI 方案中的一部分。虽然很早就开始制定这个标准,但到今天,还是有很多系统不支持 GPT。

首先,引用一张wikipedia上的结构图,来了解一下 GPT 的基本结构。

GPT 为了兼容 MBR,LBA 0 依旧保留了MBR的结构。在GPT工作是,会优先读取 GPT (LBA1) 内容。如果没有 GPT 内容,则认为这是一块MBR磁盘。再从LBA 0 读取MBR。

在硬盘末尾,GPT 备份了一份,这样当GPT出错时,可以快速的从硬盘末尾恢复。LBA -1 (负1) 表示倒数第一块 LBA。

从LBA 2 到 LBA 33 ,一共预留了 128 个分区表空间。 GPT 支持在一块硬盘上创建 128 个分区(真有这种需求?)。所以每一个分区可以使用 128 bytes 的空间。

来看一看 LBA 1 的结构吧,有了 512bytes 的巨型空间,都用不掉了。

 

0

8字节

签名(”EFI PART”, 45 46 49 20 50 41 52 54)

8

4字节

修订(比如,1.0,值是 00 00 01 00)

12

4字节

分区表头的大小(单位是字节,通常是92字节,即 5C 00 00 00)

16

4字节

分区表头前3项(第0-15字节)的CRC32校验,如果值正在计算,则是 0

20

4字节

保留,必须是 0

24

8字节

当前LBA(这个分区表头的位置)

32

8字节

备份LBA(备份分区表头的位置)

40

8字节

第一个可用于分区的LBA(主分区表的最后一个LBA + 1)

48

8字节

最后一个可用于分区的LBA(备份分区表的最后一个LBA − 1)

56

16字节

硬盘GUID(在类UNIX系统中也叫UUID

72

8字节

分区表项的起始LBA(对于主分区表来说,这个值是 LBA 2)

80

4字节

分区表的数量

84

4字节

一个分区表的大小(通常是128)

88

4字节

分区串行的CRC32校验

92

* 保留,剩余的字节必须是0(对于512字节LBA的硬盘即是420个字节)

 

此表来源为 中文 Wikipedia, 稍微修改了两个字,便于理解。

通过这张表,程序可以获知分区数量,第一个分区在哪个位置,以及GPT头是否正确(CRC32)。在这里着重解决的是分数数量问题,以及分区表的安全性问题。而分区的大小问题,则依赖了 GPT 的分区表:

 

0

16字节

分区类型GUID

16

16字节

分区GUID

32

8字节

起始LBA(小端序

40

8字节

末尾LBA

48

8字节

属性标签(如:60表示“只读”)

56

72字节

分区名(可以包括36个UTF-16(小端序)字符)

 

重点就在这里了,在描述分区位置的时候,使用了8个字节,其最大值为 FF FF FF FF FF FF FF FF 。那么,假设每一个LBA 为512 bytes。其能描述的大小为 8589934592 TB = 8 ZB 。关于这个数字我算下来的确是在 ZB 级别的。但是搜索到的文章说法不一:

突破2TB限制 3TB硬盘装操作系统实战 9.4ZB (GPT分区表采用8个字节即64bit来存储扇区数,因此它最大可支持264个扇区。) 关于windows server 2003最大支持硬盘容量的问题 18EB

对于上面这些数字,18EB 恐怕是 LBA 数量,忘记乘 512 bytes 了。9.4ZB 暂时不知道是怎么来的。但这个数字暂且不做定论。因为微软的 FAQ 也提到了,这只是理论值,谁知道下一个瓶颈在哪里呢。

Q. How big can a GPT disk be?

A. In theory, a GPT disk can be up to 2^64 logical blocks in length. Logical blocks are commonly 512 bytes in size.

The maximum partition (and disk) size is a function of the operating system version. Windows XP and the original release of Windows Server 2003 have a limit of 2TB per physical disk, including all partitions. For Windows Server 2003 SP1, Windows XP x64 edition, and later versions, the maximum raw partition of 18 exabytes can be supported. (Windows file systems currently are limited to 256 terabytes each.)

 

Linux:如何在 Ubuntu 启用 Radeon 开源驱动的 UVD 硬件解码

Phoronix 今天公布了在 Ubuntu 启用 Radeon 开源驱动 UVD 硬件解码的方法。

首先,你需要一块 Radeon HD 4000 系列或更新的显卡。然后,可以按照以下步骤逐步安装:

  • 安装 VPDAU 的头文件:sudo apt-get install libvdpau-dev
  •  Mesa 的 Git 仓库抓取最新代码,加上 –with-gallium-drivers=r600 –enable-vdpau 编译参数进行编译安装。
  • 在 /etc/ld.so.conf.d/z.conf 加上 /usr/local/lib/vdpau 参数,没有这个配置文件可自行创建,然后执行 ldconfig 命令。
  • 安装 drm-next 分支的 3.10 内核,可以从 Ubuntu Mainline Kernel PPA 下载安装。下载地址
  • 下载 GPU 对应型号的 UVD Firmware 并放入到 /lib/firmware 目录,若不清楚显卡型号,可以全部下载。下载地址 
  • 重启电脑,选择新内核进入系统。
  • 使用兼容 VDPAU 接口的播放器进行播放即可。

提示一:Linux 版本的 Flash Player 是通过 VDPAU 获得 GPU 硬件解码的,理论上 Flash Player 也可以利用 UVD 进行播放视频。

提示二:其他发行版可以参考以上指南,根据实际环境配置和调整。

结合早前 Phoronix 进行的 Radeon Gallium3D 性能测试,AMD 的 Radeon 开源驱动进展良好,某程度上开源驱动和 Catalyst 闭源驱动的差距越来越小。有组建 Linux HTPC 的朋友可以考虑一下。使用笔记本的朋友,还是先安抚一下电池君,给多一点耐心吧。

Phoronix 原文链接 

via http://linuxtoy.org/archives/how-to-useopen-source-radeon-uvd-on-ubuntu.html

 

Linux:Facebook如何实现PB级别数据库自动化备份

Facebook的MySQL数据库,是世界上最庞大的MySQL数据库之一,在不同地区有数千个数据库服务器。因此,备份对他们来说是个巨大的挑战。为了解决这个问题,他们构建了一个高度自动化、非常有效的备份系统,每周移动多个PB的数据。Facebook数据团队的Eric Barrett通过一篇文章分享了他们的做法。

他们没有采用大量前载(front-loaded)测试,而是强调快速检测失败,并且进行快速、自动化纠正。部署几百个数据库服务器,只需很少人力干预。使用下面的三个措施,他们做到了有节奏的增长,同时具备支持上十亿用户的灵活性。

措施1:二进制日志和mysqldump

第一道防线称为“措施1”,或“机架”备份(rack backup),简称RBU。在每个数据库机架上,不论其类型为何,都有两个RBU存储服务器。以RBU作为数据库服务器放在同一个机架中,这可以保证最大的带宽和最小的延迟,它们同时可以作为缓存,在备份的下个措施使用。

收集二进制日志,是这些服务器的工作之一。二进制日志会不断以流形式,通过模拟从进程(simulated slave process)输送到RBU主机中。这样一来,不需要运行mysqld,RBU就可以接收到同样的更新作为复制版本。

在RBU上保存同步的二进制日志很重要:如果一个主数据库服务器离线,该服务器上的用户将无法更新状态或是上传照片。出现问题后,他们需要保证修复时间越短越好。有可用的二进制日志,就能让他们在数秒内启动另一个数据库作为主数据库。由于RBU中有秒级的二进制日志,即使某个旧主数据库完全不可用,也没有关系,只要利用将记录下的事务恢复到上一个备份中即可完成立即恢复。

RBU服务器的第二个工作是执行传统备份。MySQL备份有两种方式:二进制和逻辑(mysqldump)。Facebook使用逻辑备份,因为它与版本无关,提供更好的数据完整性,更紧凑,恢复起来更省事。不过,当为某个数据库构建全新复制时,他们仍然使用二进制拷贝。

mysqldump的一个主要好处是:磁盘上的数据损坏不会影响到备份中。如果磁盘某个扇区出现问题,或是写入错误,InnoDB页面校验和就会出错。在组合备份流时,MySQL会从内存中读取正确的内容,或是去磁盘读取,然后遇到错误的校验和,停止备份(以及数据库进程)。mysqldump的问题是:污染用来缓存InnoDB块的LRU缓存。不过,新版本的MySQL中,会将LRU插入操作从扫描时放到缓存结束。

对在自己权限范围内的所有数据库,每个RBU都有一个夜间备份。尽管有着天量级别的数据,Facebook的团队还是可以在几个小时内完成对所有数据的备份。

如果RBU失败,自动化软件会将其职责分配给同一集群中其他系统。当它恢复上线后,职责会自动返回到最初的RBU主机。

Facebook团队不会过分担心单个系统的数据保留问题,因为他们有措施2。

措施2:Hadoop DFS

在每个备份和二进制日志收集完成后,他们会马上将其复制到他们的大型定制化Hadoop集群中。这些集群是非常稳定的复制数据集,并有固定的保留时间。因为磁盘大小增长很快,较老的RBU可能不足以保存一到两天的备份。不过他们会按需要增长Hadoop集群,同时不需要担心底层硬件情况。Hadoop的分布式特性让他们有足够带宽,完成快速数据恢复。

不久,他们会把非实时数据分析放到这些Hadoop集群中。这可以降低数据库中非关键读的次数,让Facebook网站的响应速度更快。

措施3:长期存储

每周,他们会从Hadoop备份移动到另一个地区的分散存储中。这些系统是最新而且安全的存储系统,在他们的日常数据管理工具流程之外。

监控

除常用的系统监控外,他们还会捕捉很多特定的统计数据,比如binlog集合延迟、系统容量等等。

为备份失败打分,是他们最有价值的工具。因为Facebook的数据库和同时运行的维护任务量级,错过某些备份也不奇怪。广泛的失败和多日没有成功的单个备份,这都是他们要注意的重点。因此,某个错过备份的得分会随着时间呈指数级增长,这些得分的不同聚合,让团队能对备份的整体健康度有一个有效而快速的了解。

比如,在一天内,某个数据错失一次备份,得1分,一天错失50次备份,就是50分。但在三天内的一次数据库错失,就是27分(3的3次幂),三天内50次,这是很严重的问题,得分就是1350(50乘以3的3次幂)。这会在他们的监控图上出现一个巨大的波峰,团队会马上对其采取行动。

恢复

在系统管理员中有句老话:“如果你没有测试过你的备份,就等于没有备份。”

因此,Facebook团队构建了一个测试系统,会持续地从措施2开始,将数据恢复到测试服务器上。恢复完成后,他们会执行多次数据完整性检查。如果有任何反复出现的问题,系统就会报警,提醒相关人员关注、审核。该系统可以发现所有问题,包括MySQL的bug,到备份过程中的纰漏,并可以让他们更灵活地应对备份环境中的变化。

他们构建了一个名为ORC(ORC恢复协调器的递归缩写)的系统,工程师如何需要恢复他们所用工具的数据库的过去版本,就可以以自服务方式使用该系统恢复数据。对于快速开发来说还是挺方便的。

在结尾,Eric Barrett说道:

备份不是最迷人的工程工作。它们即是技术活,又是重复性的,如果一切正常,没人会注意。它们也是跨学科和团队的,需要懂得系统、网络和软件等多方面的专业知识。但是,确保你的记忆和联系安全无误,这是无比重要的事情,而且到最后,也是充满回报的事情。

有网友问到:

在不运行mysqld的RBU上,你们如何完成二进制日志的流传送?什么是模拟从进程?

Facebook的MySQL性能工程师Harrison Fisk给出了答案:

我们使用mysqlbinlog的–never–选项,并有一个用python开发的小包装程序,会监控并保证mysqlbinlog运行成功。

来源:InfoQ-郑柯 

Linux:理性选择key-value Store

前言

开源产品固然好,但是各种场景的数据需求确实多少有些差距,利用现有的软硬件资源面对现有的问题快速做出调整是才是数据库工程师的真正价值。

综述

key-value store由于本身实现不像成熟RDBMS那么复杂,换句话说开发周期不常,性能更是由于去掉了ACID的约束,从一个个benchmark上看对比起主流开源关系型数据库mysql innodb的曲线都非常好看,op/s号称高一个数量级的不是没有,request latency更是有redis类似的内存性数据库,在高并发的场景下99.95%响应在1ms以下一点也不惊奇。其实对于了解oltp数据系统的同学来说,这其实一点也不神奇。


Linux:每日Ubuntu小技巧 – 改变Ubuntu Unity启动器尺寸

这里有一些给新Ubuntu用户的小技巧。这一系列的小技巧是为了帮助Ubuntu新用户轻松地配置和管理他们的电脑。这不是面向专家用户的,只是为了那些刚刚开始使用Ubuntu的用户。

Ubuntu启动器是Ubuntu Unity桌面的关键部分。启动器是一个布满图标的垂直条,当你登陆的时候,它就会位于屏幕的左边栏。通过它您可以从桌面方便地打开或者启动程序,还可以让您快速访问应用、工作空间、可移动设备和垃圾桶。

默认情况下,这个启动器图标大小被设置为48X48px,即使是较小的屏幕上也如此。如果你需要调大或调小启动器的尺寸,那么请继续接下来的学习。

想调整Unity启动器尺寸的原因有很多。其中一个就是为了适应更小的屏幕。如果你的屏幕很小,默认尺寸不合适,那么你就需要改变它了。

如果图标默认尺寸太小,想要增大它,则可以调整启动器来增大图标,从而容易点击。

下面开始调整大小,点击右上角的齿轮按钮弹出菜单条,点击系统设置(System Settings…),如下图。

接下来,选择 外观(Appearance)

最后,使用滚动条来调整(增大\减小)启动器的图标尺寸。

这个改变会被自动应用。记住,如果你想要继续作用默认尺寸,移动到48.

这是另一个为Ubuntu新用户的小技巧。欢迎回来掌握更多的Ubuntu小技巧。如果你是一个老手并且想要做出贡献,就请在下面留言吧。

享受吧!

via: http://www.liberiangeek.net/2013/09/daily-ubuntu-tips-resize-ubuntu-unity-launcher/

本文由 LCTT 原创翻译,Linux中国 荣誉推出

译者:Vic___ 校对:jasminepeng

来源:https://linux.cn/article-2243-1.html

Linux:Linux 下使用Trickle限制下载/上传带宽

你有没有遇到过一个程序占用了你所有的网络带宽的情况?如果你遇到过,那么你就需要限制带宽的应用。不管你是一个系统管理员还是一名普通Linux用户,您都应该学习如何控制应用的上传和下载速度来确保你的网络带宽不会被一个程序耗光。

Trickle 是什么?

Trickle是一款带宽控制供给,用来限制如Firefox, FTP , SSH以及其他使用网络带宽的程序的带宽。你希望你的Youtube音乐体验影响到你的ftp下载么?如果不想,请继续阅读这篇文章,学习如何在你的机器上安装和使用trickle。

怎样在Linux上安装Trickle

trickle工具有一些依赖包,安装和使用trickle之前必须安装“libevent 库”,不过这个库在大多数现在的Linux机器上已经默认安装。

在 Debian/Ubuntu/Linux Mint 上

Debian/Ubuntu/Mint 机器上运行 apt-get install trickle进行安装。请确保源列表已经更新,接着安装你想要的应用。

$ sudo apt-get update
$ sudo apt-get install trickle

在 RHEL/CentOS/Fedora 上

首先你需要更新系统,然后使用下面的命令安装trickle。

# yum update
# yum install trickle

Trickle如何工作?

Trickle通过控制socket数据读写量来控制和限制应用的上传/下载速度。它使用另一个版本的BSD套接字API,但是区别是trickle还管理socket调用。

要注意的是trickle使用动态链接和加载,所以它只对于使用”Glibc库”的程序有用。由于trickle可以设置数据在socket上的传输延迟,所以它可以用来限制一个应用的网络带宽。

Trickle不能做什么?

Trickle不能用于限制使用UDP协议的应用的带宽,它只可用于TCP连接,但是你要知道它也并不是对所有的TCP连接有效。如果你一直仔细地看这篇文章,你可以猜到原因是什么。你还记得trickle只对使用Glibc库应用有效吧?

还要说一下,trickle无法工作在使用静态链接的可执行程序上。

确定Trickle是否可运行在某个特定应用上

既然trickle无法限制每个应用的上传/下载速度,就应该有个方法找出trickle可以工作的应用。

ldd工具可以帮我们找出某个特定的程序是否使用了libc.so库。如果程序使用了这个库,就可以使用trickle来限制它的网络带宽使用。

ldd命令用于打印每个程序需要的共享库。如果你是一个好奇的Linux Geek,那么你可以使用man命令来找出关于ldd工具的更多信息。

# man ldd

Filezilla是一款使用ftp协议传输文件的程序,trickle可以用来限制它的下载或者上传速度么?在你考虑的时候,我使用以下的命令来找出trickle是否可用于filezilla。

# ldd filezilla | grep libc.so

就我而言,它输出了如下:

oltjano@oltjano-X55CR:/usr/bin$ ldd filezilla | grep libc.so
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb6bc4000)

既然filezilla使用了“libc.so”库,那么trickle可以用来限制它的网络带宽。这个方法可以用在任何你感兴趣的程序上。

学习如何使用Trickle

使用下面的命令输出trickle工具的版本

root@oltjano-X55CR:~# trickle -V
trickle: version 1.07

Linux有很多命令行工具使测试(实验)变得有趣和美丽。下面的命令使用wget 工具来下载最新的Pear OS镜像.

root@oltjano-X55CR:~# wget http://sourceforge.net/projects/pearoslinux/files/Pear%20OS%208/pearos8-i386.iso/download
--2013-11-20 11:56:32--  http://sourceforge.net/projects/pearoslinux/files/Pear%20OS%208/pearos8-i386.iso/download
Resolving sourceforge.net (sourceforge.net)... 216.34.181.60
Connecting to sourceforge.net (sourceforge.net)|216.34.181.60|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://downloads.sourceforge.net/project/pearoslinux/Pear%20OS%208/pearos8-i386.iso?r=&ts=1384928843&use_mirror=kaz [following]
--2013-11-20 11:56:33--  http://downloads.sourceforge.net/project/pearoslinux/Pear%20OS%208/pearos8-i386.iso?r=&ts=1384928843&use_mirror=kaz
Resolving downloads.sourceforge.net (downloads.sourceforge.net)... 216.34.181.59
Connecting to downloads.sourceforge.net (downloads.sourceforge.net)|216.34.181.59|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://kaz.dl.sourceforge.net/project/pearoslinux/Pear%20OS%208/pearos8-i386.iso [following]
--2013-11-20 11:56:33--  http://kaz.dl.sourceforge.net/project/pearoslinux/Pear%20OS%208/pearos8-i386.iso
Resolving kaz.dl.sourceforge.net (kaz.dl.sourceforge.net)... 88.204.157.163
Connecting to kaz.dl.sourceforge.net (kaz.dl.sourceforge.net)|88.204.157.163|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1093664768 (1.0G) [application/octet-stream]
Saving to: ‘download’
0% [                                                                                                    ] 30,78,278    381KB/s  eta 1h 50m

从输出可以看到,下载速度大约是381 KB/s。我想限制下载速度到13 K/s,这样我就可以用我的带宽做其他的事情了。下面的命令用来限制wget速度到13 K/s

ravisaive@ravisaive-OptiPlex-380:~$ trickle -d 13 wget http://sourceforge.net/projects/pearoslinux/files/Pear%20OS%208/pearos8-i386.iso/download
--2013-11-20 12:01:19--  http://sourceforge.net/projects/pearoslinux/files/Pear%20OS%208/pearos8-i386.iso/download
Resolving sourceforge.net (sourceforge.net)... 216.34.181.60
Connecting to sourceforge.net (sourceforge.net)|216.34.181.60|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://downloads.sourceforge.net/project/pearoslinux/Pear%20OS%208/pearos8-i386.iso?r=&ts=1384929129&use_mirror=kaz [following]
--2013-11-20 12:01:19--  http://downloads.sourceforge.net/project/pearoslinux/Pear%20OS%208/pearos8-i386.iso?r=&ts=1384929129&use_mirror=kaz
Resolving downloads.sourceforge.net (downloads.sourceforge.net)... 216.34.181.59
Connecting to downloads.sourceforge.net (downloads.sourceforge.net)|216.34.181.59|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://kaz.dl.sourceforge.net/project/pearoslinux/Pear%20OS%208/pearos8-i386.iso [following]
--2013-11-20 12:01:20--  http://kaz.dl.sourceforge.net/project/pearoslinux/Pear%20OS%208/pearos8-i386.iso
Resolving kaz.dl.sourceforge.net (kaz.dl.sourceforge.net)... 88.204.157.163
Connecting to kaz.dl.sourceforge.net (kaz.dl.sourceforge.net)|88.204.157.163|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1093664768 (1.0G) [application/octet-stream]
Saving to: ‘download.1’
0% [                                                                                                   ] 2,01,550    13.1KB/s  eta 21h 5m

从输出可以看到,下载速度被限制到了13K/s。下载将会持续21小时5分钟。上面的“-d”选项表示下载,还可以结合使用 “-d”选项和上传选项(-u),如下例所示。

# trickle -u 100 -d 50 ftp

上面的命令限制ftp 客户端的上传速度为100K/s,下载速度为50K/s。还可以使用下面的命令,限制在一个shell里运行的所有命令的带宽。

trickle -d 130 -u 13 bash

每个命令行工具都对用户提供了帮助,使用”trickle -h”命令来找出更多trickle工具的用法。

root@oltjano-X55CR:/usr/bin# trickle -h
Usage: trickle [-hvVs] [-d ] [-u ] [-w ] [-t ]
               [-l ] [-n ] command ...
    -h Help (this)
    -v Increase verbosity level
    -V Print trickle version
    -s Run trickle in standalone mode independent of trickled
    -d     Set maximum cumulative download rate to  KB/s
    -u     Set maximum cumulative upload rate to  KB/s
    -w   Set window length to  KB
    -t  Set default smoothing time to  s
    -l   Set default smoothing length to  KB
    -n     Use trickled socket name
    -L       Set latency to  milliseconds
    -P     Preload the specified .so instead of the default one

总结

本篇文章介绍如何在Linux机器上安装trickle工具,并用它如何做一些简单的事情。无论你为大公司工作还是自己使用,trickle都是高级Linux用户的必备工具。


via: http://www.tecmint.com/manage-and-limit-downloadupload-bandwidth-with-trickle-in-linux/

译者:geekpi 校对:jasminepeng

本文由 LCTT 原创翻译,Linux中国 荣誉推出

来源:https://linux.cn/article-2375-1.html

Linux:Linux系统监控神器–Collectl

系统资源监控

为使系统良好运转,Linux系统管理员经常需要监测cpu,内存,磁盘,网络等系统信息。Linux上已有iotop,top,free,htop,sar等丰富的常规工具来实现监测功能。今天让我们走进Collectl来了解这个集测试/监控/分析系统性能为一体的Linux工具。

Collectl作为一个轻量级的监控工具,在同类工具中是功能最全的。用户可监测不同的复杂系统矩阵值,并可保留数据以做之后的分析。不同于其他只用来监测特定系统参数的工具,Collectl可以同时监测不同的变量,并以合适的方式记录它们。

摘自Collectl官网

不同于或聚焦于一小组统计数据、采用唯一输出方式,或采用迭代、作为守护进程运行的大部分监测工具,collectl可以同时全部实现。用户可选择各种子系统中的任一系统来监测包括内存,CPU,磁盘,索引节点,无线带宽,lustre,内存,网络,网络文件系统,进程,二次型,slabs,套接口及TCP等信息。

深入学习前让我们先看以下命令。

$ collectl
waiting for 1 second sample...
#<--------CPU--------><----------Disks-----------><----------Network---------->
#cpu sys inter  ctxsw KBRead  Reads KBWrit Writes   KBIn  PktIn  KBOut  PktOut
   0   0   864   1772      0      0      0      0      0      1      0       0
   5   2  1338   2734      0      0      8      2      0      0      0       1
   1   0  1222   2647      0      0     92      3      0      2      0       1
   1   0   763   1722      0      0     80      3      0      1      0       2

CPU使用率,磁盘输入输出和网络活动以每秒为单位来加载。对可以理解这些数据的人来说这些信息很容易读懂。这项列表在给定的时间间隔里会持续增加,并可直接形成一项文件跟踪日志。collectl工具提供了各种命令来对这些数据进行记录,查找及做其他处理。

安装collectl工具

对Ubuntu/Debian用户来说Collectl是默认资源,所以使用apt命令便可获取。

$ sudo apt-get install collectl

Fedora/CentOS用户使用yum命令便可获取。

$ yum install collectl

使用

必要的了解 – Collectl子系统

子系统是可检测到的不同系统资源类型。像CPU,内存,带宽等等都可构成一个子系统。只运行collectl命令将以批处理模式输出CPU,磁盘和网络子系统信息,我们在上文已看到相关内容。

从操作说明可以看到,Collectl可以识别以下子系统。

总计子系统
b - buddy info (内存片段)
c - CPU
d - Disk
f - NFS V3 Data
i - Inode and File System
j - Interrupts
l - Lustre
m - Memory
n - Networks
s - Sockets
t - TCP
x - Interconnect
y - Slabs (system object caches)
细节子系统
这是一系列的详细信息,大部分情况下都会由相应的总计数据衍生出来。目前“环境变量”和“进程”2类没有相应的总计数据。如果有3个磁盘,选择-sd,将只会看到3个磁盘组合出的单一信息。如果选择-sD,将会分别显示各磁盘信息。
C - CPU
D - Disk
E - Environmental data (fan, power, temp),  via ipmitool
F - NFS Data
J - Interrupts
L - Lustre OST detail OR client Filesystem detail
M - Memory node data, which is also known as numa data
N - Networks
T - 65 TCP counters only available in plot format
X - Interconnect
Y - Slabs (system object caches)
Z - Processes

使用“-s”来监测特定的子系统并向其添加子系统的识别项。现在让我们举几个例子。

1. 监测cpu使用率

用“-sc”实现CPU总使用率的监测

$ collectl -sc
waiting for 1 second sample...
#<--------CPU-------->
#cpu sys inter  ctxsw
   3   0  1800   3729
   3   0  1767   3599

使用“-C”观察各个单独的CPU使用情况。结果将会输出多行,分别对应一个CPU。

   $ collectl -sC
waiting for 1 second sample...
# SINGLE CPU STATISTICS
#   Cpu  User Nice  Sys Wait IRQ  Soft Steal Idle
      0     3    0    0    0    0    0     0   96
      1     3    0    0    0    0    0     0   96
      2     2    0    0    0    0    0     0   97
      3     1    0    0    0    0    0     0   98
      0     2    0    0    0    0    0     0   97
      1     2    0    2    0    0    0     0   95
      2     1    0    0    0    0    0     0   98
      3     4    0    1    0    0    0     0   95

如果需要,可以同时使用C和c来获取单项CPU监测数据和汇总数据。

2. 内存监测

使用m子系统查看内存。

$ collectl -sm
waiting for 1 second sample...
#<-----------Memory----------->
#Free Buff Cach Inac Slab  Map
   2G 220M   1G   1G 210M   3G
   2G 220M   1G   1G 210M   3G
   2G 220M   1G   1G 210M   3G

不难解释。 M用来查看更多内存的详细信息。

$ collectl -sM
waiting for 1 second sample...
# MEMORY STATISTICS
# Node    Total     Used     Free     Slab   Mapped     Anon   Locked    Inact Hit%
     0    7975M    5939M    2036M  215720K  372184K        0    6652K    1434M    0
     0    7975M    5939M    2036M  215720K  372072K        0    6652K    1433M    0

这类似于免费报告吗?

3. 查看磁盘使用情况

d和D可以查看磁盘使用的概况和详细情况。

$ collectl -sd
waiting for 1 second sample...
#<----------Disks----------->
#KBRead  Reads KBWrit Writes
      4      1    136     24
      0      0     80     13
$ collectl -sD
waiting for 1 second sample...
# DISK STATISTICS (/sec)
#          <---------reads---------><---------writes---------><--------averages--------> Pct
#Name       KBytes Merged  IOs Size  KBytes Merged  IOs Size  RWSize  QLen  Wait SvcTim Util
sda              0      0    0    0       0      0    0    0       0     0     0      0    0
sda              0      0    0    0       0      0    0    0       0     0     0      0    0
sda              1      0    2    1      17      1    5    3       2     2     6      2    1
sda              0      0    0    0      92     11    5   18      18     1    12     12    5

“–verbose”命令可以用来查看附加信息。和D命令不同,它将概况扩展,包含了更多信息。

$ collectl -sd --verbose

4. 同时报告多系统情况

如果想要同时得到CPU,内存和磁盘报告,那么同时使用子命令组合来实现。

$ collectl -scmd
waiting for 1 second sample...
#<--------CPU--------><-----------Memory-----------><----------Disks----------->
#cpu sys inter  ctxsw Free Buff Cach Inac Slab  Map KBRead  Reads KBWrit Writes
   4   0  2187   4334   1G 221M   1G   1G 210M   3G      0      0      0      0
   3   0  1896   4065   1G 221M   1G   1G 210M   3G      0      0     20      5

5. 显示统计时间

若要将每行的监测信息和时间一同显示,使用T选项。通过在“-o”参数来指定。

$ collectl -scmd -oT
waiting for 1 second sample...
#         <--------CPU--------><-----------Memory-----------><----------Disks----------->
#Time     cpu sys inter  ctxsw Free Buff Cach Inac Slab  Map KBRead  Reads KBWrit Writes
12:03:05    3   0  1961   4013   1G 225M   1G   1G 212M   3G      0      0      0      0
12:03:06    3   0  1884   3810   1G 225M   1G   1G 212M   3G      0      0      0      0
12:03:07    3   0  2011   4060   1G 225M   1G   1G 212M   3G      0      0      0      0

使用“-oTm”可将时间换成毫秒显示。

6. 改变样本计数

collectl报告的每行都是一份快照或样本,它通常设定定期间隔如1秒来取样。i可用来设置时间间隔,c用来设置样本计数。

$ collectl -c1 -sm
waiting for 1 second sample...
#<-----------Memory----------->
#Free Buff Cach Inac Slab  Map
   1G 261M   1G   1G 228M   3G

使用i命令可改变更新时间间隔。

$ collectl -sm -i2
waiting for 2 second sample...
#<-----------Memory----------->
#Free Buff Cach Inac Slab  Map
   1G 261M   1G   1G 229M   3G

上面的命令设定每2秒收集一次内存信息。

7. 像iotop一样使用collectl

top命令将collectl像iostat/top工具一样进行智能统计。列表会持续更新,且可以使用不同字段实现排序。

$ collectl --top iokb

输出如下

# TOP PROCESSES sorted by iokb (counters are /sec) 09:44:57
# PID  User     PR  PPID THRD S   VSZ   RSS CP  SysT  UsrT Pct  AccuTime  RKB  WKB MajF MinF Command
 3104  enlighte 20  2683    3 S  938M   33M  0  0.00  0.00   0  00:09.16    0    4    0    0 /usr/bin/ktorrent
    1  root     20     0    0 S   26M    3M  2  0.00  0.00   0  00:01.30    0    0    0    0 /sbin/init
    2  root     20     0    0 S     0     0  3  0.00  0.00   0  00:00.00    0    0    0    0 kthreadd
    3  root     20     2    0 S     0     0  0  0.00  0.00   0  00:00.02    0    0    0    0 ksoftirqd/0
    4  root     20     2    0 S     0     0  0  0.00  0.00   0  00:00.00    0    0    0    0 kworker/0:0
    5  root      0     2    0 S     0     0  0  0.00  0.00   0  00:00.00    0    0    0    0 kworker/0:0H
    7  root     RT     2    0 S     0     0  0  0.00  0.00   0  00:00.08    0    0    0    0 migration/0
    8  root     20     2    0 S     0     0  2  0.00  0.00   0  00:00.00    0    0    0    0 rcu_bh
    9  root     20     2    0 S     0     0  0  0.00  0.00   0  00:00.00    0    0    0    0 rcuob/0

上面的输出很像top命令,并且它以磁盘数量降序排列进程。

若只想显示上面的5项进程,可用以下命令实现

$ collectl --top iokb,5

若想学习上面的列表里哪些字段可以排序,使用如下命令

$ collectl --showtopopts
下面是应用于进程或数据的最高排序类型列表。某些情况下你可能会使用某一字段进行排序,但它并非显示的一部分。
TOP PROCESS SORT FIELDS
进程排序字段
Memory
  vsz    virtual memory
  rss    resident (physical) memory
Time
  syst   system time
  usrt   user time
  time   total time
  accum  accumulated time
I/O
  rkb    KB read
  wkb    KB written
  iokb   total I/O KB
  rkbc   KB read from pagecache
  wkbc   KB written to pagecache
  iokbc  total pagecacge I/O
  ioall  total I/O KB (iokb+iokbc)
  rsys   read system calls
  wsys   write system calls
  iosys  total system calls
  iocncl Cancelled write bytes
Page Faults
  majf   major page faults
  minf   minor page faults
  flt    total page faults
Context Switches
  vctx   volunary context switches
  nctx   non-voluntary context switches
Miscellaneous (best when used with --procfilt)
  cpu    cpu number
  pid    process pid
  thread total process threads (not counting main)
TOP SLAB SORT FIELDS
  numobj    total number of slab objects
  actobj    active slab objects
  objsize   sizes of slab objects
  numslab   number of slabs
  objslab   number of objects in a slab
  totsize   total memory sizes taken by slabs
  totchg    change in memory sizes
  totpct    percent change in memory sizes
  name      slab names

8. 像top一样使用collectl

为使collectl像top,我们只需以CPU使用率排序输出进程。

$ collectl --top

输出如下

# TOP PROCESSES sorted by time (counters are /sec) 14:08:46
# PID  User     PR  PPID THRD S   VSZ   RSS CP  SysT  UsrT Pct  AccuTime  RKB  WKB MajF MinF Command
 9471  enlighte 20  9102    0 R   63M   22M  3  0.03  0.10  13  00:00.81    0    0    0    3 /usr/bin/perl
 3076  enlighte 20  2683    2 S  521M   40M  2  0.00  0.03   3  00:55.14    0    0    0    2 /usr/bin/yakuake
 3877  enlighte 20  3356   41 S    1G  218M  1  0.00  0.03   3  10:10.50    0    0    0    0 /opt/google/chrome/chrome
 4625  enlighte 20  2895   36 S    1G  241M  2  0.00  0.02   2  08:24.39    0    0    0   12 /usr/lib/firefox/firefox
 5638  enlighte 20  3356    3 S    1G  265M  1  0.00  0.02   2  09:55.04    0    0    0    2 /opt/google/chrome/chrome
 1186  root     20  1152    4 S  502M   76M  0  0.00  0.01   1  03:02.96    0    0    0    0 /usr/bin/X
 1334  www-data 20  1329    0 S   87M    1M  2  0.00  0.01   1  00:00.85    0    0    0    0 nginx:

上面的命令也可用于显示子系统信息。

$ collectl --top -scm

9. 像ps一样列出进程

为像ps命令一样列出所有进程且没有后续更新,用“c”命令让其计数至1. $ collectl -c1 -sZ -i:1

上面的命令将会列出类似“ps -e”命令的所有进程。“procfilt”用于从所有进程中过滤出特定的进程信息。“procopts”用于指定另一组微调进程列表显示的命令。

10. 像vmstat一样使用collectl

Collectl有内置命令来完成像vmstat一样的功能。

$ collectl --vmstat
waiting for 1 second sample...
#procs ---------------memory (KB)--------------- --swaps-- -----io---- --system-- ----cpu-----
# r  b   swpd   free   buff  cache  inact active   si   so    bi    bo   in    cs us sy  id wa
  1  0      0  1733M   242M  1922M  1137M   710M    0    0     0   108 1982  3918  2  0  95  1
  1  0      0  1733M   242M  1922M  1137M   710M    0    0     0     0 1906  3886  1  0  98  0
  1  0      0  1733M   242M  1922M  1137M   710M    0    0     0     0 1739  3480  3  0  96  0

11. 子系统的详细信息

下面的命令以一秒为间隔,统计5次CPU信息并和时间一起显示出详细信息(冗长)。

$ collectl -sc -c5 -i1 --verbose -oT
waiting for 1 second sample...
# CPU SUMMARY (INTR, CTXSW & PROC /sec)
#Time      User  Nice   Sys  Wait   IRQ  Soft Steal  Idle  CPUs  Intr  Ctxsw  Proc  RunQ   Run   Avg1  Avg5 Avg15 RunT BlkT
14:22:10     11     0     0     0     0     0     0    87     4  1312   2691     0   866     1   0.78  0.86  0.78    1    0
14:22:11     15     0     0     0     0     0     0    84     4  1283   2496     0   866     1   0.78  0.86  0.78    1    0
14:22:12     17     0     0     0     0     0     0    82     4  1342   2658     0   866     0   0.78  0.86  0.78    0    0
14:22:13     15     0     0     0     0     0     0    84     4  1241   2429     0   866     1   0.78  0.86  0.78    1    0
14:22:14     11     0     0     0     0     0     0    88     4  1270   2488     0   866     0   0.80  0.87  0.78    0    0

改变”-s”变量查看不同的子系统。

总结

本文的介绍不过是对collectl这个强大工具的一些浅见。本文本希望展示它有多灵活,其实通过以上的讨论让我们了解了包括记录及回寻捕获的数据,以多种文件格式导出数据并将数据转换为可被广泛的工具分析的格式等等功能的实现。

collectl提供的另一大功能便是像服务一样运行,对远程Linux机器或完整的服务器集群提供远程监控,其表现堪称完美。

Collectl同另一批可用于处理分析收集数据的名为Collectl实用工具 (colmux, colgui, colplot)的功能相契合。如果有机会,我们在之后的文章中会介绍它们。

为更详细的了解Collectl工具,请登录它的主页来学习更多的功能。笔者建议查看FAQs来快速了解collectl,读取collectl文档获取深层次的例子。等价命令表也可定位至更多的像sar,iostat,netstat,top等和collectl功能部分等价的常用工具。


via: http://www.binarytides.com/collectl-monitor-system-resources-linux/

译者:icybreaker 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

来源:https://linux.cn/article-2830-1.html

Linux:五种方法检测你的 Linux 是32位还是64位

有的时候 Linux 新手们在下载软件的时候十分困惑,因为下载页面常常同时提供32位和64位版本的软件。所以弄清楚你的操作系统是32位的还是64位的十分重要,因为你在做很多事情的时候都需要这个信息。在这篇文章里,我们会讨论五种检测你的Linux系统是32位还是64位的方法。

检测你的 Linux 是32位还是64位的

请注意文中的这些方法是在 Ubuntu 13.10 平台测试.

1. 执行‘uname -a’ 命令

最常见的一个测试方法是运行 uname command 命令。

例如,在我的系统里,它显示了以下信息:

$ uname -a
 Linux ubuntu 3.11.0-12-generic #19-Ubuntu SMP Wed Oct 9 16:12:00 UTC 2013 i686 athlon i686 GNU/Linux

那个高亮的 i686 (or 有时候会是i386) 说明操作系统是32位的,但是如果显示的是 x86_64,那就说明这个操作系统是64位的。

2.运行 ‘uname -m’ 命令

上面的命令内涵太多了,可以用这个参数直指人心:‘uname -m’ 。

例如,在我的系统里,它显示了以下信息:

$ uname -m
 i686

这说明我的 Ubuntu Linux 系统是32位的,如果输出显示的是x86_64,就说明系统是64位的。

3.使用 file 命令

尽管这样做纯粹是炫耀技巧,但是仍然不失为一种达到目的的方法。使用这个方法,需要你运行 file 命令并带上 /sbin/init 作为参数。

举个例子:

$ file /sbin/init
 /sbin/init: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0xc0d86a25a7abb14cad4a65a1f7d03605bcbd41f6, stripped

高亮的 32-bit 说明这是一个32位的操作系统,如果显示为 64-bit 则说明操作系统是64位的

4. 使用 arch 命令

另外一个可以选择的方法是使用 arch 命令,这个命令用于输出机器的硬件名称。

这里有一个示例:

$ arch
 i686

在这里你可以看到输出的是 i686, 这说明这是一个32位操作系统,对于64位的操作系统,输出的应该是x86_64。

5. 通过系统设置的方法

如果你使用的是 Ubuntu 12.04 或更高, 你可以很简单地在** All Settings -> Details**里查看你的系统结构。

details

这样你就可以看到系统类型(32-bit)在这里清晰地显示出来。

你还知道别的方法来检测操作系统是32位还是64位的吗?在下面回复与我们分享吧。


via: http://mylinuxbook.com/5-ways-to-check-if-linux-is-32-bit-or-64-bit/

译者:crowner 校对:Caroline

本文由 LCTT 原创翻译,Linux中国 荣誉推出

来源:https://linux.cn/article-3048-1.html

Python解析HTML表格的方法

Python解析HTML表格是如何来实现的呢?下面的内容将会通过具体的实例来演示Python解析HTML表格的实现方法及相关技巧:

本文实例讲述了Python实现简单HTML表格解析的方法。分享给大家供大家参考。具体分析如下:

这里依赖libxml2dom,确保首先安装!导入到你的脚步并调用parse_tables() 函数。

1. source = a string containing the source code you can pass in just the table or the entire page code

2. headers = a list of ints OR a list of strings
If the headers are ints this is for tables with no header, just list the 0 based index of the rows in which you want to extract data.
If the headers are strings this is for tables with header columns (with the tags) it will pull the information from the specified columns

3. The 0 based index of the table in the source code. If there are multiple tables and the table you want to parse is the third table in the code then pass in the number 2 here

It will return a list of lists. each inner list will contain the parsed information.

具体代码如下:

#The goal of table parser is to get specific information from specific
#columns in a table.
#Input: source code from a typical website
#Arguments: a list of headers the user wants to return
#Output: A list of lists of the data in each row
import libxml2dom
def parse_tables(source, headers, table_index):
  """parse_tables(string source, list headers, table_index)
    headers may be a list of strings if the table has headers defined or
    headers may be a list of ints if no headers defined this will get data
    from the rows index.
    This method returns a list of lists
    """
  #Determine if the headers list is strings or ints and make sure they
  #are all the same type
  j = 0
  print 'Printing headers: ',headers
  #route to the correct function
  #if the header type is int
  if type(headers[0]) == type(1):
    #run no_header function
    return no_header(source, headers, table_index)
  #if the header type is string
  elif type(headers[0]) == type('a'):
    #run the header_given function
    return header_given(source, headers, table_index)
  else:
    #return none if the headers aren't correct
    return None
#This function takes in the source code of the whole page a string list of
#headers and the index number of the table on the page. It returns a list of
#lists with the scraped information
def header_given(source, headers, table_index):
  #initiate a list to hole the return list
  return_list = []
  #initiate a list to hold the index numbers of the data in the rows
  header_index = []
  #get a document object out of the source code
  doc = libxml2dom.parseString(source,html=1)
  #get the tables from the document
  tables = doc.getElementsByTagName('table')
  try:
    #try to get focue on the desired table
    main_table = tables[table_index]
  except:
    #if the table doesn't exits then return an error
    return ['The table index was not found']
  #get a list of headers in the table
  table_headers = main_table.getElementsByTagName('th')
  #need a sentry value for the header loop
  loop_sentry = 0
  #loop through each header looking for matches
  for header in table_headers:
    #if the header is in the desired headers list
    if header.textContent in headers:
      #add it to the header_index
      header_index.append(loop_sentry)
    #add one to the loop_sentry
    loop_sentry+=1
  #get the rows from the table
  rows = main_table.getElementsByTagName('tr')
  #sentry value detecting if the first row is being viewed
  row_sentry = 0
  #loop through the rows in the table, skipping the first row
  for row in rows:
    #if row_sentry is 0 this is our first row
    if row_sentry == 0:
      #make the row_sentry not 0
      row_sentry = 1337
      continue
    #get all cells from the current row
    cells = row.getElementsByTagName('td')
    #initiate a list to append into the return_list
    cell_list = []
    #iterate through all of the header index's
    for i in header_index:
      #append the cells text content to the cell_list
      cell_list.append(cells[i].textContent)
    #append the cell_list to the return_list
    return_list.append(cell_list)
  #return the return_list
  return return_list
#This function takes in the source code of the whole page an int list of
#headers indicating the index number of the needed item and the index number
#of the table on the page. It returns a list of lists with the scraped info
def no_header(source, headers, table_index):
  #initiate a list to hold the return list
  return_list = []
  #get a document object out of the source code
  doc = libxml2dom.parseString(source, html=1)
  #get the tables from document
  tables = doc.getElementsByTagName('table')
  try:
    #Try to get focus on the desired table
    main_table = tables[table_index]
  except:
    #if the table doesn't exits then return an error
    return ['The table index was not found']
  #get all of the rows out of the main_table
  rows = main_table.getElementsByTagName('tr')
  #loop through each row
  for row in rows:
    #get all cells from the current row
    cells = row.getElementsByTagName('td')
    #initiate a list to append into the return_list
    cell_list = []
    #loop through the list of desired headers
    for i in headers:
      try:
        #try to add text from the cell into the cell_list
        cell_list.append(cells[i].textContent)
      except:
        #if there is an error usually an index error just continue
        continue
    #append the data scraped into the return_list
    return_list.append(cell_list)
  #return the return list
  return return_list
 


Python解析HTML表格就是这样,欢迎大家参考。。。。

Linux:如何在 CentOS 中设置 NTP 服务器

网络时间协议(NTP)用来同步网络上不同主机的系统时间。你管理的所有主机都可以和一个指定的被称为 NTP 服务器的时间服务器同步它们的时间。而另一方面,一个 NTP 服务器会将它的时间和任意公共 NTP 服务器,或者你选定的服务器同步。由 NTP 管理的所有系统时钟都会同步精确到毫秒级。

在公司环境中,如果他们不想为 NTP 传输打开防火墙,就有必要设置一个内部 NTP 服务器,然后让员工使用内部服务器而不是公共 NTP 服务器。在这个指南中,我们会介绍如何将一个 CentOS 系统配置为 NTP 服务器。在介绍详细内容之前,让我们先来简单了解一下 NTP 的概念。

为什么我们需要 NTP?

由于制造工艺多种多样,所有的(非原子)时钟并不按照完全一致的速度行走。有一些时钟走的比较快而有一些走的比较慢。因此经过很长一段时间以后,一个时钟的时间慢慢的和其它的发生偏移,这就是常说的 “时钟漂移” 或 “时间漂移”。为了将时钟漂移的影响最小化,使用 NTP 的主机应该周期性地和指定的 NTP 服务器交互以保持它们的时钟同步。

在不同的主机之间进行时间同步对于计划备份、入侵检测记录、分布式任务调度或者事务订单管理来说是很重要的事情。它甚至应该作为日常任务的一部分。

NTP 的层次结构

NTP 时钟以层次模型组织。层级中的每层被称为一个 stratum(阶层)。stratum 的概念说明了一台机器到授权的时间源有多少 NTP 跳。

Stratum 0 由没有时间漂移的时钟组成,例如原子时钟。这种时钟不能在网络上直接使用。Stratum N (N > 1) 层服务器从 Stratum N-1 层服务器同步时间。Stratum N 时钟能通过网络和彼此互联。

NTP 支持多达 15 个 stratum 的层级。Stratum 16 被认为是未同步的,不能使用的。

准备 CentOS 服务器

现在让我们来开始在 CentOS 上设置 NTP 服务器。

首先,我们需要保证正确设置了服务器的时区。在 CentOS 7 中,我们可以使用 timedatectl 命令查看和更改服务器的时区(比如,”Australia/Adelaide”,LCTT 译注:中国可设置为 Asia/Shanghai )

# timedatectl list-timezones | grep Australia
# timedatectl set-timezone Australia/Adelaide
# timedatectl

继续并使用 yum 安装需要的软件

# yum install ntp

然后我们会添加全球 NTP 服务器用于同步时间。

# vim /etc/ntp.conf

server 0.oceania.pool.ntp.org
server 1.oceania.pool.ntp.org
server 2.oceania.pool.ntp.org
server 3.oceania.pool.ntp.org

默认情况下,NTP 服务器的日志保存在 /var/log/messages。如果你希望使用自定义的日志文件,那也可以指定。

logfile /var/log/ntpd.log

如果你选择自定义日志文件,确保更改了它的属主和 SELinux 环境。

# chown ntp:ntp /var/log/ntpd.log
# chcon -t ntpd_log_t /var/log/ntpd.log

现在初始化 NTP 服务并确保把它添加到了开机启动。

# systemctl restart ntp
# systemctl enable ntp

验证 NTP Server 时钟

我们可以使用 ntpq 命令来检查本地服务器的时钟如何通过 NTP 同步。

下面的表格解释了输出列。

remote 源在 ntp.conf 中定义。‘*’ 表示当前使用的,也是最好的源;‘+’ 表示这些源可作为 NTP 源;‘-’ 标记的源是不可用的。
refid 用于和本地时钟同步的远程服务器的 IP 地址。
st Stratum(阶层)
t 类型。 ‘u’ 表示单播(unicast)。其它值包括本地(local)、多播(multicast)、广播(broadcast)。
when 自从上次和服务器交互后经过的时间(以秒数计)。
poll 和服务器的轮询间隔,以秒数计。
reach 表示和服务器交互是否有任何错误的八进制数。值 337 表示 100% 成功(即十进制的255)。
delay 服务器和远程服务器来回的时间。
offset 我们服务器和远程服务器的时间差异,以毫秒数计。
jitter 两次取样之间平均时差,以毫秒数计。

控制到 NTP 服务器的访问

默认情况下,NTP 服务器允许来自所有主机的查询。如果你想过滤进来的 NTP 同步连接,你可以在你的防火墙中添加规则过滤流量。

# iptables -A INPUT -s 192.168.1.0/24 -p udp --dport 123 -j ACCEPT
# iptables -A INPUT -p udp --dport 123 -j DROP

该规则允许从 192.168.1.0/24 来的 NTP 流量(端口 UDP/123),任何其它网络的流量会被丢弃。你可以根据需要更改规则。

配置 NTP 客户端

1. Linux

NTP 客户端主机需要 ntpupdate 软件包来和服务器同步时间。可以轻松地使用 yum 或 apt-get 安装这个软件包。安装完软件包之后,用服务器的 IP 地址运行下面的命令。

# ntpdate 

基于 RHEL 和 Debian 的系统命令都相同。

2. Windows

如果你正在使用 Windows,在日期和时间设置(Date and Time settings)下查找网络时间(Internet Time)。

3. Cisco 设备

如果你想要同步 Cisco 设备的时间,你可以在全局配置模式下使用下面的命令。

# ntp server 

来自其它厂家的支持 NTP 的设备有自己的用于网络时间的参数。如果你想将设备和 NTP服务器同步时间,请查看设备的说明文档。

结论

总而言之,NTP 是在你的所有主机上同步时钟的一个协议。我们已经介绍了如何设置 NTP 服务器并使支持 NTP 的设备和服务器同步时间。

希望能对你有所帮助。


via: http://xmodulo.com/setup-ntp-server-centos.html

作者:Sarmed Rahman 译者:ictlyh 校对:wxy

本文由 LCTT 原创翻译,Linux中国 荣誉推出

来源:https://linux.cn/article-5581-1.html

CentOS 6.5: 如何配置双网卡绑定

在centos 6.5 系统下,如何来配置双网卡的绑定呢,当一个网卡down掉后,另一个网卡会自动起作用,这样就不影响系统的正常通讯。
linux操作系统
1.首先通过ifconfig -a | grep eth 来查看系统下有哪些网络接口卡。
[cc lang=”php”] [devops@devops Desktop]$ ifconfig | grep eth
eth0 Link encap:Ethernet HWaddr 00:0C:29:53:85:56
eth1 Link encap:Ethernet HWaddr 00:0C:29:53:85:60
[/code] 2. 编辑”/etc/sysconfig/network-scripts/ifcfg-eth0″ 配置文件,修改下面的内容:
[cc lang=”php”] DEVICE=eth0
ONBOOT=yes
BOOTPROTO=none    
MASTER=bond0
SLAVE=yes
[/code] 3. 编辑“/etc/sysconfig/network-scripts/ifcfg-eth1″配置文件,修改下面的内容:
[cc lang=”php”] DEVICE=eth1
ONBOOT=yes
BOOTPROTO=none    
MASTER=bond0
SLAVE=yes
[/code] 4. 在”/etc/sysconfig/network-scripts/”目录下创建bond0 的配置文件,并加入下面的内容:
[cc lang=”php”] DEVICE=bond0
BOOTPROTO=static
IPADDR=192.168.42.155
NETMASK=255.255.255.0
GATEWAY=192.168.42.1
BORADCAST=192.168.42.255
DNS1=8.8.8.8
ONBOOT=yes
TYPE=Ethernet
[/code] 5.编辑/etc/modprobe.d/dist.conf 配置文件绑定模型,加入下面的你内容:
[cc lang=”php”] alias bond0 bonding
options bond0 miimon=100 mode=0
[/code] mode是设置网卡绑定的模式。
网卡绑定有七种模式:
[cc lang=”php”] mode=0 round-robin
mode=1 active-backup
mode=2 load balancing (xor)
mode=3 fault-tolerance (broadcast)
mode=4 lacp
mode=5 transmit load balancing
mode=6 adaptive load balancing
[/code] 1)轮询策略(Round-robin policy),模式代号是0。该策略是按照设备顺序依次传输数据包,直到最后一个设备。这种模式提供负载均衡和容错能力。
(2)活动备份策略(Active-backup policy),模式代号是1。该策略只有一个设备处理数据,当它宕机的时候就会由备份代替,仅提供容错能力。
(3)异或策略(XOR policy),模式代号是2。该策略是根据MAC地址异或运算的结果来选择传输设备,提供负载均衡和容错能力。
(4)广播策略(Broadcast policy),模式代号是3。该策略通过全部设备来传输所有数据,提供容错能力。
(5)IEEE 802.3ad 动态链接聚合(IEEE 802.3ad Dynamic link aggregation),模式代号是4。该策略通过创建聚合组来共享相同的传输速度,需要交换机也支持 802.3ad 模式,提供容错能力。
(6)适配器传输负载均衡(Adaptive transmit load balancing),模式代号是5。该策略是根据当前的负载把发出的数据分给每一个设备,由当前使用的设备处理收到的数据。本策略的通道联合不需要专用的交换机支持,提供负载均衡和容错能力。
(7)适配器负载均衡(Adaptive load balancing),模式代号是6。该策略在IPV4情况下包含适配器传输负载均衡策略,由ARP协商完成接收的负载,通道联合驱动程序截获ARP在本地系统发送出的请求,用其中一个设备的硬件地址覆盖从属设备的原地址。
6. 修改”/etc/rc.local”文件,添加下面的内容,是系统在启动的时候将网卡绑定:
[cc lang=”php”] ifenslave bond0 eth2 eth3
[/code] 7.重启网络服务
使用下面的命令:
[cc lang=”php”] service network restart
[/code] [cc lang=”php”] root@devops Desktop]# service network restart
Shutting down loopback interface: [ OK ] Bringing up loopback interface: [ OK ] [/code] 到此双网卡绑定配置完成。。
当你一个网卡出问题后,另一块网卡会继续工作,不影响系统之家的正常网络通讯。

哪家互联网公司压榨员工最严重?

bat com

富 士康、三星、华为、格力,这些耳熟能详的知名企业,也曾成为雇佣童工、过劳死、血汗工厂的代名词。如今,随着互联网行业竞争的白热化,越来越多的业内人开 始抱怨有关于职场中遇到的种种不公:没有加班费;管理混乱;工作环境恶劣;升职空间被卡死,各种口水满天飞。女人被当成男人用,男人被当牲口用;女汉纸、 壮丁,也成了互联网公司职员相互调侃的口头语。
总之,领导和员工的关系就好像天平的两端,一不小心就会失去平衡。以下文字摘自知乎网友的各种吐槽爆料
小米:变相让员工推销
用户1:宅青
小米是血汗工厂,一开始一周六天朝十晚十,后来勉强改成一周五天,但是如果周六要上班,都是直接邮件一句话通知。绝无加班补助这种东西。像@王子君 这样做营销的估计一周休息时间更少,经常看他三更半夜在抽烟,做方案。在小米就是用青春奉献小米的明天。
讲 个段子。前年小米年会,有个许愿树环节,全体员工写个愿望,每个合伙人都抽一个愿望帮助满足。本以为大家会写出国旅游,苹果电脑啥的。结果全场抽奖只有一 两个人是物质愿望,其余全部是希望周末不上班,晚上不加班。可见民怨。现场好不尴尬,没有一个合伙人敢承诺未来可以一天不上十二个小时。到最后主持人都挂 不住了,但凡遇到不加班的愿望,统统作废,重抽。结果,呵呵,越废越多,整个环节雷总脸都绿了。
在小米工作两年,身体状况每况愈下,面临婚事,唯独跳槽过的更轻松。我相信离开小米的有绝大一部分是因为累。
第 二个原因是抠门。所有领导都擅长画大饼。理想很大很忽悠,刚到公司说好好干今后有期权,结果期权干满五年才有,然后又承诺会有小米公寓,前1000员工免 费入住,好么现在大楼选址还没选。管理层也是精明到家的人,给员工奖励无非就是自家产品和友商产品,变相让员工推销。到头来,人人都热血沸腾而来,未必能 共苦走到最后。
华为:要员工自愿放弃休假等法定假期
用户2:匿名用户
冒着跑题的风险也要来黑一下华为,算不上互联网公司,但是,压榨员工的伎俩让人无语。还是匿了吧
华为待遇,跟互联网公司相比,表面上看是差不多的,但实际上要差很多。
1、奋斗者协议。这个最变态,要员工自己申请:自愿放弃年休假等法定假期。(是感觉贱贱的,但如果不申请,呵呵。。。。)
2、不论什么请假方式(甚至病假)超过一定时间,将会影响到你的考评。这个就很严重,要知道,他的工资并不高,要是影响了你的奖金,你这个请假就好值钱了啊。
3、根据部门不同,若是倒霉,你的部门加班木有加班费,那就惨了,美其名曰“调休”,但是,想请假不给你批啊!批了也要影响你的考评啊!影响了就木有钱了啊!相当于加了班还扣钱啊!所以,一般人都尽量不请假,你辛辛苦苦赚钱是为啥???给别人花吧。
4、工资低,靠年终奖,年终奖还要推迟到年中才发,其中奥妙,大家想必都明白的。太坑爹了。
亚马逊:管理混乱,人事变动大

用户3:白霄

北美码农说一句,我知道的米帝大互联网公司里或者it公司比较狠的,以身边同学的例子(基本都是待了不到一年就想跳槽了),自然是amazon无疑了。
以下评论来自网络,但和我知道的基本相符
1、不给办绿卡。这个最扯淡,也是我认为2年内一定要离开亚马逊的理由。有例外,我也知道有些人可以办,但是太麻烦、太随机,还不如做题跳槽升工资简单明快。
2、传统部门升级慢,Sde I 到 II 有些居然要4年,当然有的好部门只需要1年多。
3、管理混乱,人事变动大。有个牛逼老中干了1年半跑了,主要是他换了5个manager,受不了了。人事变动、reorg的主要问题是本来老板答应你升级,结果老板自己跑了,这……
4、Oncall极其恶心。这个看脸,有些组其实oncall跟没有差不多,但是很多组一周7-24call你10次、20次,直接帮你倒时差了。有娃有家别去亚马逊是肯定的。
5、工作环境恶劣。停车费劲、中午吃饭费劲不说,办公室跟网吧差不多,人喊马嘶,吵得很,没有任何免费饮料喝,甚至连电脑都慢得要死,真不知道亚马逊怎么想的,developer居然还在电脑上省钱……
酷派:一周必须上六天班
用户4:匿名用户
没人说酷派?不科学吧。酷派封闭听说过么?一周必须上六天班,硬性规定每晚必须10:30之后才能打卡下班,事实上几乎从来都是晚上十二点才下班。加班费?没听过。工资高?不可能,要不然离职率也不会高的离谱吧。

Linux/Centos:如何安装/配置Nginx

nginx2Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,Nginx,它的发音为“engine X”,是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP 代理服务器。Nginx是由俄罗斯人 Igor Sysoev为俄罗斯访问量第二的 Rambler.ru站点开发的,它已经在该站点运行超过两年半了。Igor Sysoev在建立的项目时,使用基于BSD许可。下面我们来看看如何在centos系统里安装并配置Nginx.
1.在nginx官方网站下载一个rpm包,下载地址是:http://nginx.org/en/download.html

wget http://nginx.org/packages/centos/6/noarch/RPMS/
nginx-release-centos-6-0.el6.ngx.noarch.rpm
 

2.安装这个rpm包

rpm -ivh nginx-release-centos-6-0.el6.ngx.noarch.rpm
 

安装过程中会出现错误提示:

warning: nginx-release-centos-6-0.el6.ngx.noarch.rpm:
Header V4 RSA/SHA1 Signature, key ID 7bd9bf62: NOKEY

不知道干什么的,忽略即可
3.开始正式安装nginx

yum install nginx
 

会显示一大堆信息,问你ok不ok啊:Is this ok [y/N]:
输入y,屏幕滚了一会之后就安装完毕,最后提示“Complete!”就是安完了。
4.nginx的几个默认目录
whereis nginx
nginx: /usr/sbin/nginx /etc/nginx /usr/share/nginx
1 配置所在目录:/etc/nginx/
2 PID目录:/var/run/nginx.pid
3 错误日志:/var/log/nginx/error.log
4 访问日志:/var/log/nginx/access.log
5 默认站点目录:/usr/share/nginx/html
5.常用命令
1 启动nginx:nginx
2 重启nginx:killall -HUP nginx
3 测试nginx配置:nginx -t
6.Nginx无法站外访问?
刚安装好nginx一个常见的问题是无法站外访问,本机wget、telnet都正常。而服务器之外,不管是局域网的其它主机还是互联网的主机都无法访问站点。如果用telnet的话,提示:
正在连接到192.168.0.xxx…不能打开到主机的连接, 在端口 80: 连接失败
如果用wget命令的话,提示:
Connecting to 192.168.0.100:80… failed: No route to host.
如果是以上的故障现象,很可能是被CentOS的防火墙把80端口拦住了,尝试执行以下命令,打开80端口:

iptables -I INPUT -p tcp –dport 80 -j ACCEPT
 

然后用:

/etc/init.d/iptables status
 

查看当前的防火墙规则,如果发现有这样一条:

ACCEPT     tcp  –  0.0.0.0/0            0.0.0.0/0           tcp dpt:80

就说明防火墙规则已经添加成功了,再在站外访问就正常了。
原文地址

Linux/Centos:如何安装GCC(C和C++编译器)

linux系统下或者Centos7/Red Hat7企业版系统里如何安装gnu下的GCC编译器以及相关的工具呢?(autoconf,automake,flex,c++ compiler)
你需要安装包含下面的软件包的基本开发工具环境,那么就会自动安装好我们想要装gcc编译器:

  1.     autoconf
  2.   automake
  3.   binutils
  4.     bison
  5.     flex
  6.     gcc
  7.     gcc-c++
  8.     gettext
  9.     libtool
  10.     make
  11.     patch
  12.     pkgconfig
  13.     redhat-rpm-config
  14.     rpm-build
  15.     rpm-sign

输入下面的命令安装基本工具开发包:

# yum group install “Development Tools"
 

下一步可以用whereis gcc这个命令来验证是否安装成功:

[root@devops ~]# whereis gcc
gcc: /usr/bin/gcc /usr/lib/gcc /usr/libexec/gcc /usr/share/man/man1/gcc.1.gz
[root@devops ~]#
 

或者通过gcc家–version选项来查看gcc的版本号:
[cc lang=”bash] [root@devops ~]# gcc –version
gcc (GCC) 4.4.7 20120313 (Red Hat 4.8.2-16)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[/code]

程序员必看的十大电影

不同的行业领域中很多时候都分享着共同的思想和理念。比如,大量的计算机编程中涉及到的概念都被运用到了电影里。有些概念出现在电影里 后变得如此之酷,甚至反过来能帮助我们程序员更好的理解这些概念。下面就是我最喜欢的10大电影,它们都在某方便帮助了我理解编程中的某些概念。

1. 骇客帝国(1999)

概念:在线/离线,递归,循环,矩阵等。
这部具有革命性的电影。一种文明的结束是另一种文明的开始。它成了后来的很多电影效仿的对象。
programmer-movie-1

2. 环形使者(2012)

概念:循环
如果生活变成了一种无休无止的循环,如何终止它?
programmer-moviej-2

3. 创:战记(2010)

概念:虚拟和现实
很多到了年纪的计算机科学家都会承认,他们对计算机计算或战争游戏的热爱来自一种憧憬。
programmer-movie-3

4. 遇见未来(2007)

概念:递归
这部电影运用到了计算机里递归的概念,特别是最后的搜索那部分,那是在一个树数据上进行递归搜索。
programmer-movie-4

5. 死神来了 1, 2, 3, 4, 5

概念: if else jump
programmer-movie-5

6. 盗梦空间(2010)

概念:虚拟机,嵌套
盗梦空间这部影片看的糊里糊涂,主要是里面的梦境嵌套的太多了,人物在各个梦境里来回穿越,弄的我不知道究竟他们在第几层梦境。关于这部电影一则笑话却非常的有意思,如果你是个真正的程序员,你一定会哈哈大笑:

盗梦空间的主要思想是:如果你在虚拟机(VM)里的虚拟机里的虚拟机里安装了一个虚拟机,那所有的东西都会变的死慢。

programmer-movie-6

7. 云图(2012)

概念:并行
看似无关的几个线索其实是有内部联系的,就像是并行计算其实都是为了解决同一个任务,甚至还会共享一些变量。
programmer-movie-7

8. Flatland 2: Sphereland (2012)

概念:2D
programmer-movie-8

9. 源代码(2011)

概念:多线程重进入(Reentrancy)机制
我很好奇这些源代码是在什么上运行的。如果关闭电源,那另外一个世界就会消失?
programmer-movie-9

10. 恐怖游轮 (2009)

概念:死循环
programmer-movie-10
上面这些电影就是我最喜欢的一些电影。当然,还有很多跟软件编程相关的电影,如果你在评论里给我提示,我会把它们补充到这个列表里。

程序员赚钱致富的6种方法

我认识一个朋友,也是程序员出身,他在一家还不错的外企上班,每个月工资收入也就差不多15K,五年的工作经验了,在他面前,我算是小弟。那天我们几个朋友一起打完球就去附近的饭馆吃饭,环境还不错,于是就边吃边聊工作、赚钱的事情。
那天了解到,他不仅拿着15K的高薪,业余还有着更高的收入,从聊天中,我总结了几点程序员赚钱的技巧,分享给大家,也许你可以参考一下,哪天发财了记得回到这篇文章中来赞一下。

一、Google Adsense


利用Adsense可以将广告发布到你的网站上去,通过访客点击广告来赚取佣金。这似乎是一个很不错的主意,如果你有一个不错的创意,写一个网站对于程序员的你应该不难,网站放上Adsense广告,推广、引流、收美金。

二、Android App交易市场收入


首先,他的Android应用是免费的,他并不是靠卖App来赚钱,而是通过向App中投放广告来赚取佣金的。如果你对Android技术非常熟悉,或者你的工作就是做Android开发,那么为什么不自己开发一个应用放到Android市场,为自己创造另一份收入。

三、参加一些开发者大赛

这是一种最实在的方法了,拿奖金,只赚不赔,不过前提是你得有足够的实力。他参加过Google的Android开发者大赛,很得瑟的跟我们说那时 候他赢得了2000美金,尽管不是很多,但从中也可以学到不少知识,至少,通过学习,他可以自己开发Android应用来赚取广告费了。

四、承接一些项目

当然这要花费你很大一部分时间,承接时你要考虑时间成本,至少这些时间要和你的工资相当。个人不怎么推荐这种方法,有时候周期会很长,很容易丧失积极性,不过也算是一种方法。

五、刷机、越狱

现在都是智能手机,有些用久了,卡了,像电脑一样要重装系统,一些小白有教程都搞不定,这时候你可以借此开展刷机业务。还有iOS的越狱,这个需要你对iOS的操作非常熟悉。你可以将此业务挂到淘宝上,帮助买家实现他们要的功能。

六、做黑客


黑入银行,盗取前女友现任老公的所有钱,哈哈,开玩笑了。不过,做一名优秀的计算机黑客确实可以帮你赚取很大一笔收入,比如帮助一些企业提高计算机网络的安全性、做一些抵御攻击的积极措施等。
这是我们讨论结果的几个要点,因人而异,如果你要更好的建议,欢迎在评论中告诉我们。
原文地址

Linux:如何通过命令行来设置日期和时间

在linux下如何设置日期和时间呢?假如你的linux系统没有安装GUI,而只能通过ssh或者telnet登陆到linux操作系统里,如何在linux操作系统下设置日期呢?
使用date命令来显示当前的日期和时间或者设置系统日期和时间,如果系统的时间是错误的,那么可以使用date命令来重新设置。
你必须以root用户来执行date命令。
linux显示当前的日期和时间
输入下面的命令:

[root@devops sh]# date
Wed Jun  4 21:49:35 CST 2014
[root@devops sh]#

Linux显示硬件时钟
输入下面的hwclock命令来读取硬件时钟,并在屏幕上显示时间:

root@devops sh]# hwclock -r
Wed 04 Jun 2014 09:50:00 PM CST  -0.334125 seconds

或者

[root@devops sh]# hwclock --show
Wed 04 Jun 2014 09:51:23 PM CST  -0.185823 seconds

Linux设置时间的例子
使用下面的方法来设置日期和时间:

date --set="STRING"

设置新的日期为:Thu 05 Jun 2014 05:51:45, 输入下面的命令:

#date -s “Thu 05 Jun 2014 05:51:45”

或者

#date --set="Thu 05 Jun 2014 05:51:45"

你也可以使用下面的方法来简化格式:

#date +%Y%m%d -s "20140603"

Linux设置时间的例子
使用下面的方法来设置时间:

#date +%T -s "14:32:22"

其中:

14:小时
32:分钟
13:秒

参考:Man命令帮助-hwclock, date 

ubuntu下中文输入法的安装–fcitx

在自己电脑上装了ubuntu系统以来 一直没有怎么用过 今天打开电脑想着配置一下环境 在查资料的时候难免的要输入中文然后自己弄了一下中文输入法的安装 我安装的是fcitx小企鹅输入法 下面介绍一下安装的过程。。。。。
1.打开终端 输入

sudo add-apt-repository ppa:wengxt/fcitx-nightly
2.按ENTER键确认安装

3.接着输入
sudo apt-get update

4.sudo apt-get install fcitx fcitx-config-gtk fcitx-sunpinyin
5:安装过程中有Y/N选择的都输入Y,然后按回车继续。


6:继续输入下面命令安装其它码表。y继续

sudo apt-get install fcitx-table-all


7:安装好后假如系统内有多个输入法的话,则输入下面命令,把fcitx设置为默认输入法,一般都不用输入。(网上查询到的有这一步 但是我没做)

im-switch -s fcitx -z default
8:为了防止乱码,安装uming字体,继续输入下面命令。
sudo apt-get install ttf-arphic-uming


9:fcitx安装完成,重启一下ubuntu系统。
当你打开电脑的时候 CTRL+空格 你的输入法就出来
原文地址

OpenBSD:如何挂载USB闪存盘/移动硬盘

在OpenBSD 操作系统下,如何在命令行下挂载和使用USB闪存盘或者移动硬盘呢?OpenBSD系统支持通过模拟SCSI接口的方式来使用USB存储设备(优盘或者移动硬盘),你需要以root用户的方式登陆OpenBSD系统来挂载USB盘。
先获取USB设备在OpenBSD系统上的名字
首先要在USB接口上插入你的USB盘,然后输入下面的命令来显示设备名:

#sysctl hw.disknames

示例输出:

hw.disknames=wd0:3af96a8b7d621ab2,cd0:,sd0:

获取更多的关于sd0的信息,输入下面的命令:

#dmesg | grep sd0

命令输出如下:

sd0 at scsibus1 targ 1 lun 0:  SCSI2 0/direct removable
sd0: 1956MB, 512 bytes/sector, 4005888 sectors
sd0 detached
sd0 at scsibus1 targ 1 lun 0:  SCSI2 0/direct removable
sd0: 1956MB, 512 bytes/sector, 4005888 sectors

下面的命令也会显示出更多的关于sd0的信息:

#disklabel sd0

命令输出如下:

# /dev/rsd0c:
type: vnd
disk: vnd device
label: fictitious
duid: 97d41b01a9d85387
flags:
bytes/sector: 512
sectors/track: 100
tracks/cylinder: 1
sectors/cylinder: 100
cylinders: 5120
total sectors: 4005888
boundstart: 0
boundend: 512000
drivedata: 0
16 partitions:
#                size           offset  fstype [fsize bsize  cpg]
a:           512000                0  4.2BSD   2048 16384    1
c:          4005888                0  unused
#

在OpenBSD系统上挂载USB闪存盘或者移动硬盘
首先输入下面的命令来创建挂载目录:

#mkdir /mnt/usbdisk

接着使用mount命令来挂载闪存盘,输入命令:

#mount /dev/sd0 /mnt/usbdisk

然后你就可以访问你挂载上的USB闪存盘或者移动硬盘里的数据

#cd /mnt/usbdisk
#ls -l

如果你要卸载闪存盘或者移动硬盘,可以输入下面的命令:

#umount /mnt/usbdisk

解决”/bin/dbus-launch terminated abnormally without any error message“错误信息的问题

当在redhat或者centos系统下运行下面的命令的时候会遇到下面的错误信息,百度之后发下是redhat/centos的bug,那么如何来修复呢?

ssh -X
firefox &

错误信息为:
[cc lang=”php”] **error**: Failed to contact configuration server; some possible causes are that you need to enable TCP/IP networking for ORBit, or you have stale NFS locks due to a system crash. See http://projects.gnome.org/gconf/ for information. (Details – 1: Failed to get connection to session: /bin/dbus-launch terminated abnormally without any error message)
[/code] 首先要通过yum命令安装D-Bus和Fonts包:
[cc lang=”php”] [root@devops ~]# yum install dbus-x11
Loaded plugins: fastestmirror
Determining fastest mirrors
 * base: mirrors.163.com
 * extras: mirrors.163.com
 * updates: mirrors.163.com
base                                                                      | 3.7 kB     00:00     
extras                                                                    | 3.4 kB     00:00     
gf                                                                        | 2.9 kB     00:00     
updates                                                                   | 3.4 kB     00:00     
updates/primary_db                                                        | 3.1 MB     00:03     
Setting up Install Process
Resolving Dependencies
Dependencies Resolved
=================================================================================================
 Package                  Arch              Version                        Repository       Size
=================================================================================================
Installing:
 dbus-x11                 x86_64            1:1.2.24-7.el6_3               base             40 k
Installing for dependencies:
 dbus                     x86_64            1:1.2.24-7.el6_3               base            207 k
 libX11                   x86_64            1.5.0-4.el6                    base            584 k
 libX11-common            noarch            1.5.0-4.el6                    base            192 k
 libXau                   x86_64            1.0.6-4.el6                    base             24 k
 libxcb                   x86_64            1.8.1-1.el6                    base            110 k
Updating for dependencies:
 dbus-libs                x86_64            1:1.2.24-7.el6_3               base            127 k
Transaction Summary
=================================================================================================
Install       6 Package(s)
Upgrade       1 Package(s)
Total download size: 1.3 M
Is this ok [y/N]:
[/code] 再安装Fonts包,输入下面的命令:
[cc lang=”php”] [root@devops ~]# yum groupinstall ‘Fonts’
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.163.com
* extras: mirrors.163.com
* updates: mirrors.163.com
Setting up Group Process
Checking for new repos for mirrors
base/group_gz                                                        
Resolving Dependencies
[/code] 当安装了这两个包后,问题就应该能解决了。

Grep:grep显示匹配到的行数目

我们如何知道匹配某个字符串或者单词在文件或者标准输入里总共有多少行?我们如何获取匹配到的行的数目呢?

你需要使用grep命令的-c 或者–count选项来控制grep命令的输出,让grep命令的输出只显示匹配到的行数:

[root@devops ~]# grep -c user1 /etc/passwd
2
[root@devops ~]# grep --count user1 /etc/passwd
2
[root@devops ~]# grep user1 /etc/passwd
user1:x:501:501::/home/user1:/bin/bash
user1add:x:503:503::/home/user1add:/bin/bash
[root@devops ~]# 

如果使用-v 或者–invert-match 选项,可以显示不匹配的行的数目:

[root@devops ~]# grep -cv user1 /etc/passwd
25
[root@devops ~]# grep -c --invert-match user1 /etc/passwd
25
[root@devops ~]#

Grep:grep匹配行所在文件的文件名

当我们在大量文件中使用grep命令来查找匹配行,有时候可能需要只显示匹配行所在文件的文件名,那么如何才能只显示匹配行所在文件的文件名呢?

普通的grep命令查找:

[root@devops ~]# grep user1 /etc/*
/etc/group:user1:x:501:
/etc/group:user1add:x:503:
/etc/group-:user1:x:501:
/etc/group-:user1add:x:503:
/etc/gshadow:user1:!::
/etc/gshadow:user1add:!::
/etc/gshadow-:user1:!::
/etc/gshadow-:user1add:!::
/etc/passwd:user1:x:501:501::/home/user1:/bin/bash
/etc/passwd:user1add:x:503:503::/home/user1add:/bin/bash
/etc/passwd-:user1:x:501:501::/home/user1:/bin/bash
/etc/passwd-:user1add:x:503:503::/home/user1add:/bin/bash
/etc/shadow:user1:!!:16176:0:99999:7:::
/etc/shadow:user1add:!!:16176:0:99999:7:::
/etc/shadow-:user1:!!:16176:0:99999:7:::
/etc/shadow-:user1add:!!:16176:0:99999:7:::
[root@devops ~]# 

从上面的输出结果,可以看出来第一个字段是文件名,在grep命令里,可以使用-l选项来控制grep命令的输出,只显示匹配行的文件名。

[root@devops ~]# grep -l user1 /etc/*
/etc/group
/etc/group-
/etc/gshadow
/etc/gshadow-
/etc/passwd
/etc/passwd-
/etc/shadow
/etc/shadow-
[root@devops ~]#

如果想显示不匹配行所在文件的文件名,可以使用-L选项:

[root@devops ~]# grep -l user1 /etc/*
/etc/group
/etc/group-
/etc/gshadow
/etc/gshadow-
/etc/passwd
/etc/passwd-
/etc/shadow
/etc/shadow-
[root@devops ~]#