上一篇文章说道虽然使用了VNC来远程桌面连接,但是效率实在是低,网上看到的一些文章也印证了这个事实,于是又开始了探索之旅。

首先是尝试使用了NoMachine,一款商业化的远程桌面控制解决方案,效率也比VNC有了质的提升,但是拖动窗口时会出现些许失真,这还是在虚拟机里,不存在网络传输的问题,观看视频看来是不行了,虽然用来看视频的可能性很小,但是总归不好,有没有更好的解决方案呢?不得不说,我这眼睛算是被splashtop养刁钻了。

第二款尝试的是x2go,基于NoMachine开源的代码开发的一款开源解决方案,但是在我的测试环境下愣是没成功,连接后黑屏

dpkg -i Splashtop_Streamer_Ubuntu_14.04_v2.2.5.1-4_amd64.deb 
正在选中未选择的软件包 splashtop-streamer。
(正在读取数据库 ... 系统当前共安装有 179342 个文件和目录。)
正准备解包 Splashtop_Streamer_Ubuntu_14.04_v2.2.5.1-4_amd64.deb  ...
正在解包 splashtop-streamer (2.2.5.1-1) ...
dpkg: 依赖关系问题使得 splashtop-streamer 的配置工作不能继续:
 splashtop-streamer 依赖于 libapr1 (>= 1.4.8-2~);然而:
  未安装软件包 libapr1。
 splashtop-streamer 依赖于 libaprutil1 (>= 1.2.7+dfsg);然而:
  未安装软件包 libaprutil1。
 splashtop-streamer 依赖于 libx264-142;然而:
  未安装软件包 libx264-142。
 splashtop-streamer 依赖于 python-webkit (>= 1.1.8);然而:
  未安装软件包 python-webkit。

dpkg: 处理软件包 splashtop-streamer (--install)时出错:
 依赖关系问题 - 仍未被配置
正在处理用于 bamfdaemon (0.5.3+16.10.20160929-0ubuntu1) 的触发器 ...
Rebuilding /usr/share/applications/bamf-2.index...
正在处理用于 gnome-menus (3.13.3-6ubuntu4) 的触发器 ...
正在处理用于 desktop-file-utils (0.23-1ubuntu1) 的触发器 ...
正在处理用于 mime-support (3.60ubuntu1) 的触发器 ...
在处理时有错误发生:
 splashtop-streamer

可以看到缺少libapr1、libaprutil1、libx264-142、python-webkit 4个依赖,其中libapr1 libaprutil1 python-webkit可使用apt直接安装,libx264-142则从launchpad.net搜索下载deb包

然后执行


dpkg -i Splashtop_Streamer_Ubuntu_14.04_v2.2.5.1-4_amd64.deb libx264-142_0.142.2495+git6a301b6-1ubuntu1_amd64.deb

安装就完成了,最后搜索运行splashtop streamer,并设为开机启动

目前电脑打算换平台,换下来的配件本着物尽其用的原则打算用作NAS。

抛开痛苦的NAS系统选择阶段,最终打算以ubuntu16.04系统为基础,但是作为现代NAS系统,远程终端控制未免太显简陋,而且也不人性化,还是远程桌面连接来的实在,局域网内带宽延迟不是问题。

话说linux下远程桌面第一想到的也就是VNC,不巧ubuntu之前的unity桌面与xrdp 不兼容,费时好久终于找到了一个略显完美的解决方案,操作也比较简单。测试系统为ubuntu16.10,16.04同样适用。

1、打开桌面共享-共享-勾选“允许其他人查看您的桌面”,和“允许其他用户控制您的桌面”

桌面共享

2、安装并打开,展开org->gnome->desktop->remote-access,选择启用,将requre-encryption设为false

dconf-editor

然后使用VNCViewer连接就可以了

但目前看来速度并不理想,窗口拖动时明显出现撕裂,对于我来讲这是不能忍的,没有找到优化方法的话看来只能换别的方法了

浏览网站时看到了一些不错的图片想要收藏,单个保存太麻烦,数量大的话操作相当繁琐,于是尝试使用wget命令抓取并过滤掉不需要的文件

一条命令就可解决:

wget -e robots=off -A jpg -nd -np -r -l 2 -H -D img1.mydrivers.com http://news.mydrivers.com/1/505/505136.htm

-e robots=off 忽略robots

-A jpg 只接受jpg格式

-nd 不建立目录

-np 不追溯至父目录

-H 递归时转向外部主机

-D 可接受的域名列表(逗号分隔)

wget参数详解

启动:
  -V,  --version                   显示 Wget 的版本信息并退出
  -h,  --help                      打印此帮助
  -b,  --background                启动后转入后台
  -e,  --execute=命令              运行一个“.wgetrc”风格的命令

日志和输入文件:
  -o,  --output-file=文件          将日志信息写入 FILE
  -a,  --append-output=文件        将信息添加至 FILE
  -d,  --debug                     打印大量调试信息
  -q,  --quiet                     安静模式 (无信息输出)
  -v,  --verbose                   详尽的输出 (此为默认值)
  -nv, --no-verbose                关闭详尽输出,但不进入安静模式
       --report-speed=类型         以 <类型> 报告带宽。类型可以是 bits
  -i,  --input-file=文件           下载本地或外部 <文件> 中的 URL
  -F,  --force-html                把输入文件当成 HTML 文件
  -B,  --base=URL                  解析相对于 URL 的 HTML 输入文件链接 (-i -F)
       --config=文件               指定要使用的配置文件
       --no-cookies                不读取任何配置文件
       --rejected-log=文件         将拒绝 URL 的原因写入 <文件>。

下载:
  -t,  --tries=数字                设置重试次数为 <数字> (0 代表无限制)
       --retry-connrefused         即使拒绝连接也是重试
  -O,  --output-document=文件      将文档写入 FILE
  -nc, --no-clobber                不要下载已存在将被覆盖的文件
  -c,  --continue                  断点续传下载文件
       --start-pos=偏移量          从由零计数的 <偏移量> 开始下载
       --progress=类型             选择进度条类型
       --show-progress             在任意啰嗦状态下都显示进度条
  -N,  --timestamping              只获取比本地文件新的文件
       --no-if-modified-since      不要在时间戳 (timestamping) 模式下使用
                                     if-modified-since get 条件请求
       --no-use-server-timestamps  不根据服务器上的时间戳设置本地文件的时间戳
  -S,  --server-response           打印服务器响应
       --spider                    不下载任何文件
  -T,  --timeout=SECONDS           将所有超时设为 SECONDS 秒
       --dns-timeout=SECS          设置 DNS 查寻超时为 SECS 秒
       --connect-timeout=SECS      设置连接超时为 SECS 秒
       --read-timeout=SECS         设置读取超时为 SECS 秒
  -w,  --wait=SECONDS              等待间隔为 SECONDS 秒
       --waitretry=SECONDS         在获取文件的重试期间等待 1..SECONDS 秒
       --random-wait               获取多个文件时,每次随机等待间隔 (0.5~1.5)*WAIT 秒
       --no-proxy                  禁止使用代理
  -Q,  --quota=数字                设置获取配额为 <数字> 字节
       --bind-address=ADDRESS      绑定至本地主机上的 ADDRESS (主机名或是 IP)
       --limit-rate=RATE           限制下载速率为 RATE
       --no-dns-cache              关闭 DNS 查询缓存
       --restrict-file-names=系统  限定文件名中的字符为 <系统> 允许的字符
       --ignore-case               匹配文件/目录时忽略大小写
  -4,  --inet4-only                仅连接至 IPv4 地址
  -6,  --inet6-only                仅连接至 IPv6 地址
       --prefer-family=地址族      首先连接至指定家族(IPv6,IPv4 或 none)的地址
       --user=用户                 将 ftp 和 http 的用户名均设置为 <用户>
       --password=密码             将 ftp 和 http 的密码均设置为 <密码>
       --ask-password              提示输入密码
       --no-iri                    关闭 IRI 支持
       --local-encoding=ENC        使用 ENC 作为 IRI (国际化资源标识符) 的本地编码
       --remote-encoding=ENC       使用 ENC 作为默认远程编码
       --unlink                    覆盖前移除文件

目录:
  -nd, --no-directories            不创建目录
  -x,  --force-directories         强制创建目录
  -nH, --no-host-directories       不要创建主 (host) 目录
       --protocol-directories      在目录中使用协议名称
  -P,  --directory-prefix=前缀     保存文件到 <前缀>/..
       --cut-dirs=数字             忽略远程目录中 <数字> 个目录层。

HTTP 选项:
       --http-user=用户            设置 http 用户名为 <用户>
       --http-password=密码        设置 http 密码为 <密码>
       --no-cache                  不使用服务器缓存的数据。
       --default-page=NAME         改变默认页 (通常是“index.html”)。
  -E,  --adjust-extension          以合适的扩展名保存 HTML/CSS 文档
       --ignore-length             忽略头部的‘Content-Length’区域
       --header=字符串             在头部插入 <字符串>
       --max-redirect              每页所允许的最大重定向
       --proxy-user=用户           使用 <用户> 作为代理用户名
       --proxy-password=密码       使用 <密码> 作为代理密码
       --referer=URL               在 HTTP 请求头包含‘Referer: URL’
       --save-headers              将 HTTP 头保存至文件。
  -U,  --user-agent=代理           标识自己为 <代理> 而不是 Wget/VERSION。
       --no-http-keep-alive        禁用 HTTP keep-alive (持久连接)。
       --no-cookies                不使用 cookies。
       --load-cookies=文件         会话开始前从 <文件> 中载入 cookies。
       --save-cookies=文件         会话结束后保存 cookies 至 FILE。
       --keep-session-cookies      载入并保存会话 (非永久) cookies。
       --post-data=字符串          使用 POST 方式;把 <字串>作为数据发送。
       --post-file=文件            使用 POST 方式;发送 <文件> 内容。
       --method=HTTP方法           在请求中使用指定的 <HTTP 方法>。
       --post-data=字符串          把 <字串> 作为数据发送,必须设置 --method
       --post-file=文件            发送 <文件> 内容,必须设置 --method
       --content-disposition       当选择本地文件名时允许 Content-Disposition
                                   头部 (实验中)。
       --content-on-error          在服务器错误时输出接收到的内容
       --auth-no-challenge         不先等待服务器询问就发送基本 HTTP 验证信息。

HTTPS (SSL/TLS) 选项:
       --secure-protocol=PR         选择安全协议,可以是 auto、SSLv2、
                                    SSLv3、TLSv1、PFS 中的一个。
       --https-only                 只跟随安全的 HTTPS 链接
       --no-check-certificate       不要验证服务器的证书。
       --certificate=文件           客户端证书文件。
       --certificate-type=类型      客户端证书类型,PEM 或 DER。
       --private-key=文件           私钥文件。
       --private-key-type=类型      私钥文件类型,PEM 或 DER。
       --ca-certificate=文件        带有一组 CA 证书的文件。
       --ca-directory=DIR           保存 CA 证书的哈希列表的目录。
       --ca-certificate=文件        带有一组 CA 证书的文件。
       --pinnedpubkey=FILE/HASHES  Public key (PEM/DER) file, or any number
                                   of base64 encoded sha256 hashes preceded by
                                   'sha256//' and seperated by ';', to verify
                                   peer against
       --random-file=文件           用于初始化 SSL 伪随机数生成器(PRNG)的文件,
                                      应含有随机数据
       --egd-file=文件              用于命名带有随机数据的 EGD 套接字的文件。

HSTS 选项:
       --no-hsts                   禁用 HSTS
       --hsts-file                 HSTS 数据库路径(将覆盖默认值)

FTP 选项:
       --ftp-user=用户             设置 ftp 用户名为 <用户>。
       --ftp-password=密码         设置 ftp 密码为 <密码>
       --no-remove-listing         不要删除‘.listing’文件
       --no-glob                   不在 FTP 文件名中使用通配符展开
       --no-passive-ftp            禁用“passive”传输模式
       --preserve-permissions      保留远程文件的权限
       --retr-symlinks             递归目录时,获取链接的文件 (而非目录)

FTPS 选项:
       --ftps-implicit                 使用隐式 FTPS(默认端口 990)
       --ftps-resume-ssl               打开数据连接时继续控制连接中的 SSL/TLS 会话
       --ftps-clear-data-connection    只加密控制信道;数据传输使用明文
       --ftps-fallback-to-ftp          回落到 FTP,如果目标服务器不支持 FTPS
WARC 选项:
       --warc-file=文件名          在一个 .warc.gz 文件里保持请求/响应数据
       --warc-header=字符串        在头部插入 <字符串>
       --warc-max-size=数字        将 WARC 的最大尺寸设置为 <数字>
       --warc-cdx                  写入 CDX 索引文件
       --warc-dedup=文件名         不要记录列在此 CDX 文件内的记录
       --no-warc-compression       不要 GZIP 压缩 WARC 文件
       --no-warc-digests           不要计算 SHA1 摘要
       --no-warc-keep-log          不要在 WARC 记录中存储日志文件
       --warc-tempdir=目录         WARC 写入器的临时文件目录

递归下载:
  -r,  --recursive                 指定递归下载
  -l,  --level=数字                最大递归深度 (inf 或 0 代表无限制,即全部下载)。
       --delete-after             下载完成后删除本地文件
  -k,  --convert-links            让下载得到的 HTML 或 CSS 中的链接指向本地文件
       --convert-file-only         只转换 URL 的文件部分 (通常所谓的 basename)
       --backups=N                 写入文件 X 前,轮换移动最多 N 个备份文件
  -K,  --backup-converted         在转换文件 X 前先将它备份为 X.orig。
  -m,  --mirror                   -N -r -l inf --no-remove-listing 的缩写形式。
  -p,  --page-requisites          下载所有用于显示 HTML 页面的图片之类的元素。
       --strict-comments          用严格方式 (SGML) 处理 HTML 注释。

递归接受/拒绝:
  -A,  --accept=列表               逗号分隔的可接受的扩展名列表
  -R,  --reject=列表               逗号分隔的要拒绝的扩展名列表
       --accept-regex=REGEX        匹配接受的 URL 的正则表达式
       --reject-regex=REGEX        匹配拒绝的 URL 的正则表达式
       --regex-type=类型           正则类型 (posix|pcre)
  -D,  --domains=列表              逗号分隔的可接受的域名列表
       --exclude-domains=列表      逗号分隔的要拒绝的域名列表
       --follow-ftp                跟踪 HTML 文档中的 FTP 链接
       --follow-tags=列表          逗号分隔的跟踪的 HTML 标识列表
       --ignore-tags=列表          逗号分隔的忽略的 HTML 标识列表
  -H,  --span-hosts                递归时转向外部主机
  -L,  --relative                  仅跟踪相对链接
  -I,  --include-directories=列表  允许目录的列表
       --trust-server-names        使用重定向 URL 的最后一段作为本地文件名
  -X,  --exclude-directories=列表  排除目录的列表
  -np, --no-parent                 不追溯至父目录

在网络编码中会发现程序在局域网中是可以适用的,但是在外网与内网之间和内网与内网之间就不可行。 
问题就在于NAT。首先介绍下NAT。 
NAT的作用NAT(Network Address Translator),网络地址转换。顾名思义,它是一种把内部私有网络IP地址翻译成公有网络IP地址的技术,如图5-1所示。NAT是在IP地址日益缺乏的情况下产生的,它的主要目的是使地址能够重用[9]。 
NAT模型
图5-1 NAT模型 
IP地址分为五类:A类,B类,C类,D类,E类(这里不考虑保留的IP地址)。A、B、C类可被计算机作为IP地址,D类为组播地址,E类为特殊用途的地址。A、B、C类中,又可分为公有地址和私有地址,私有地址用于内网,不同的内网,私有地址可重用,从而节省了公网地址,它不可在公网中被路由,所以内网的主机要访问公网的服务器,便要经过NAT。公有地址是全球唯一的,能在公网上被路由。 
NAT的作用
内网主机用私有地址在内网能与其它的内网主机无误地通信,但它不能直接用私有地址访问外网的主机,因为私有地址不能被路由。它要与外网通信,必须经过NAT设备(如网关,路由器),如图5-2所示。主机A与服务器S通信,它须先通过网关,此时网关改变它的数据包地址及端口,把私有地址(10.0.0.2)改为公有地址(155.99.25.11),使数据包能在公网上被路由,送至服务器端。服务器端返回的数据包到达网关后,网关把公网地址改为相应的私有地址,然后转发到主机A。通过这种方法,一个内网只需一个公有IP地址,就把整个内网的计算机接入Internet,从而解决IP地址缺乏的问题。 
NAT功能通常被集成到路由器、防火墙、ISDN路由器或者单独的NAT设备中。也可通过软件实现这一功能,Windows 98 SE、Windows 2000 都包含了这一功能。 
NAT的分类及工作原理 
nat%e7%9a%84%e5%88%86%e7%b1%bb

基本NAT与NAPT如图5-3所示,NAT分为两大类,基本的NAT和NAPT(Network Address/Port Translator)[10][11]。 
基本的NAT,它仅将内网主机的私有IP地址转换成公网IP地址,但并不将TCP/UDP端口信息进行转换,有动态与静态之区分。由于现在大部分都属于另一种类型,即NAPT,故这里不详细讨论基础NAT。 
另外一种NAT叫做NAPT(Network Address/Port Translator),从名称上我们也可以看得出,NAPT不但会改变经过这个NAT设备的IP数据报的IP地址,还会改变IP数据报的TCP/UDP端口。NAPT的地址及端口的转换过程,请看图5-4: 
NAPT的地址及端口转换过程
私有网络中某一主机Client A(10.0.0.2),它的某个进程通过1234端口,想访问外网服务器18.181.0.31的1235端口。那么当数据包通过NAT时,这个NAT的外网地址是155.99.25.11,首先NAT会改变这个数据包的原IP地址,改为155.99.25.11。并分配一个端口(如62000)给Client A,把数据包的原端口号改为62000。所以本来是(10.0.0.2:1234->18.181.0.31:1235)的数据包到了互联网上变为了(155.99.25.11:62000->18.181.0.31:1235),如图5-4左图所示。NAT会记住62000端口对应的是10.0.0.2的1234端口,以后从外网服务器18.181.0.31发送到62000端口的数据会被NAT自动的改变目的IP和端口号,然后转发到10.0.0.2上(如图5-4右图所示) 
锥型NAT与对称型NAT 
对称性NAT与锥形NAT

NAPT又分为锥型(Cone)和对称型(Symmetric),如图5-5所示,它们的区别在于,在NAT已分配端口号给Client A的情况下,如果Client A继续用1235端口与另一外网服务器通讯,锥型NAT还会继续用原来62000端口,即所分配的端口号不变。而对于对等型NAT,NAT将会分配另一端口号(如62001)给Client A的1235端口。也就是说,同一内网主机同一端口号,对于锥型NAT,无论与哪一外网主机通讯,都不改变所分配的端口号;而对于对等型NAT,同一内网主机同一端口号,每一次与不同的外网主机通讯,就重新分配另一个端口号。 
完全锥型NAT、受限制锥型NAT与端口受限制型NAT 
锥型NAT可另外分类为完全锥形(Full Cone)NAT,受限制锥形(Restricted Cone)NAT,端口受限制锥形(Port Restricted Cone)NAT。 
①完全锥形(Full Cone)NAT 
这种NAT内部的主机A连接过外网主机C后,NAT会打开一个端口。然后外网的任何发到这个打开的端口的UDP数据报都可以到达A,不管是不是C发过来的[12]。 
例如 A: 192.168.8.100  NAT: 202.100.100.100  C: 292.88.88.88 
A(192.168.8.100:5000) -> NAT(202.100.100.100:8000) -> C(292.88.88.88:2000) 
任何发送到NAT(202.100.100.100:8000)的数据都可以到达A(192.168.8.100:5000)。 
②受限制锥形(Restricted Cone)NAT 
这种NAT内部的主机A连接过外网的主机C后,NAT打开一个端口。然后C可以用任何端口和A通信,但其他的外网主机不可以。 
例如 A: 192.168.8.100  NAT: 202.100.100.100  C: 292.88.88.88 
A(192.168.8.100:5000) -> NAT(202.100.100.100:8000) -> C(292.88.88.88:2000) 
任何从C发送到NAT(202.100.100.100:8000)的数据都可以到达A(192.168.8.100:5000)。 
③端口受限制锥形(Port Restricted Cone)NAT 
这种NAT内部的主机A连接过外网的主机C后,NAT打开一个端口。然后C只能用原来的端口和A通信,其他的外网主机不可以。 
例如 A: 192.168.8.100  NAT: 202.100.100.100  C: 292.88.88.88 
A(192.168.8.100:5000) -> NAT(202.100.100.100:8000) -> C(292.88.88.88:2000) 
只有C(202.88.88.88:2000)发送到 NAT(202.100.100.100:8000)的数据都可以到达A(192.168.8.100:5000)。 
NAT产生的问题 
NAT很好地解决了地址紧缺的问题,屏蔽了内部网络,但也带来一些问题。内网的主机向外连接是很容易的(NAT相当于透明的,内网的和外网的主机均不用知道NAT的情况)。但如果外部的计算机想访问子网内的计算机就比较困难了,这可以使内网主机先发起连接从而解决问题。但是如果两台主机都分别位于两不同NAT后面时,两台主机无法通信。当分别位于两不同NAT(NAT A,NAT B)后面的两台主机A和B欲进行通讯时,若主机B主动发起连接,它该连哪个地址呢?第一种情况:试图直接连到主机A的内网私有地址(10.0.0.2:1234)肯定会失败,因为10.0.0.2根本就不是一个可以在公网上路由的IP地址;第二种情况,试图直接连到B的NAT公有地址(155.99.25.11:62000),NAT A会拒绝这个数据包,因为这个端口并无绑定内网主机的某个端口,或即使有所绑定,但这个端口所绑定的外网地址和端口并不是B的地址和端口。若A主动连接B,结果一样。 
有两种方法解决这个问题。方法一:通过服务器,服务器作为中间人,转发主机间的数据。但若用户数量到达一定数目时,这方法浪费带宽且给服务器带来很大压力,所以方法不可行。方法二,还是通过服务器,但服务器只充当“介绍人”,不转发主机间的数据,具体请看下面的“UDP打孔技术” (UDP hole punching) 
穿透NAT——UDP打孔技术 
所谓的“打孔技术”,就是在内网的NAT设备上打上一个“孔”(也就是在NAT上建立一个会话,绑定地址和端口号),这个孔不能由外部来打,只能由内网内的主机来打。而且这个孔可能是有方向的,比如从内部某台主机(比如:192.168.0.10)向外部的某个IP(比如:219.237.60.1)发送一个UDP包,那么就在这个内网的NAT设备上打了一个方向为219.237.60.1的“孔”,以后219.237.60.1就可以通过这个孔与内网的192.168.0.10联系了[13]。 
下面就根据NAT的各种类型详细解析如何“打孔”,如何穿透NAT。 
1.完全锥形(Full Cone)NAT 
处于不同内网的主机A和主机B,各自先连接服务器,从而在各自NAT设备上打开了一个“孔”,服务器收到主机A和主机B的连接后,知道A与B的公网地址和NAT分配给它们的端口号,然后把这些NAT地址与端口号告诉A与B,由于在完全锥形NAT的特点,A和B给服务器所打开的“孔”,能给别的任何的主机使用。故A与B可连接对方的公网地址和端口直接进行通信。服务器在这里充当“介绍人”,告诉A与B对方的地址和端口号。 
2.受限制锥形(Restricted Cone)NAT 
A和B还是要先连接服务器,服务器发送A和B的地址和端口信息给A和B,但由于受限制锥形NAT的特点,他们所打开的“孔”,只能与服务器通信。要使他们可以直接通信,解决办法如下: 
假如主机A开始发送一个UDP信息到主机B的公网地址上,与此同时,它又通过服务器中转发送了一个邀请信息给主机B,请求主机B也给主机A发送一个UDP信息到主机A的公网地址上。这时主机A向主机B的公网IP发送的信息导致NAT A打开一个处于主机A的和主机B之间的会话,与此同时,NAT B也打开了一个处于主机B和主机A的会话。一旦这个新的UDP会话各自向对方打开了,主机A和主机B之间就可以直接通信了[14]。 
3.端口受限制锥形(Port Restricted Cone)NAT 
对于该类型的NAT,解决办法跟上面的方法一样。 
4.对称型(Symmetric)NAT 
对称型NAT,对于不同的外网主机地址,它都会分配不同的端口号,所以进行UDP打孔比较困难,但也可以进行端口预测打孔,不过不能保证成功。 
以上的穿透NAT,是对NAPT来进行穿透,主要是针对UDP协议。TCP协议也有可能,但是可行性非常小,要求更高。并且,语音视频通信是用UDP传输的,故针对TCP的NAT穿透在这里不作讨论。基础NAT不修改经过的数据包的端口号,它们可以看作是完全锥形NAT的精简版本,即基础NAT也可以被穿透。NAT设备将在一定时间后关闭UDP的一个映射,所以为了保持与服务器能够一直通信,服务器或客户端必须要周期性地发送UDP包,保持映射不被关闭。 
目前比较常用的NAT类型是完全锥型NAT 
穿透NAT
如图6-7所示,步骤如下: 
①客户端A发UDP数据报经NAT A,把数据发送到服务器。NAT A分配端口给客户端A。服务器接收到信息后,把客户端A经NAT A后的地址及端口信息记录下来。 
②客户端B发UDP数据报经NAT B,把数据发送到服务器。NAT B分配端口给客户端B。服务器接收到信息后,把客户端B经NAT B后的地址及端口信息记录下来。 
③ 服务器把客户端B的地址及端口信息发送给客户端A,把客户端A的地址及端口信息发送给客户端B,客户端A、B就可以通过所获得的对方的地址及端口号进行通信了。

编辑/usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf
添加:
[SeatDefaults]
user-session=ubuntu
greeter-show-manual-login=true

若想root自动登录

autologin-user=root

top太老了

与其说top太老了,不如说top的逻辑方式不再适合现代程序的交互逻辑

今天碰到了一款更为强大的进程管理工具-htop,简而言之,比top好用多了

上截图看下:
htop截图

左上角CPU,内存,SWAP使用情况,右上角任务进程启动时间

然后就是进程的详细情况,功能键基本功能都有了,而且支持鼠标操作

简洁的交互方式,鼠标就可以kill掉进程

对我来讲已经到了可以替换htop的地步了

安装:

早期htop放在SourceForge.net上,现在的URL地址

多种发行版的包管理器已经提供支持

例如Ubuntu直接输入命令

apt install htop

即可

CentOS相对麻烦一些需要加入Fedora源,不过我通过源码编译安装的方式

1、下载源码包

wget http://hisham.hm/htop/releases/2.0.2/htop-2.0.2.tar.gz

2、编译安装一气呵成

./configure --prefix=/usr/local/htop && make && make install

注:./configure –prefix=/usr/local/htop可能提示
configure: error: You may want to use –disable-unicode or install libncursesw.

安装ncurses-devel即可

3、建立软链接

ln -s /usr/local/htop/bin/htop /usr/bin/

一般来讲到这里就完成了,但是我的环境比较复杂,OpenVZ的虚拟化

root@localhost:~/htop-2.0.2# ./configure --prefix=/usr/local/htop
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking target system type... x86_64-unknown-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for gcc... no
checking for cc... no
checking for cl.exe... no
configure: error: in `/root/htop-2.0.2':
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details

首先安装gcc

root@localhost:~/htop-2.0.2# yum install gcc
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
* base: repos.lax.quadranet.com
* extras: repos.dfw.quadranet.com
* updates: mirrors.usc.edu
正在解决依赖关系
-- 正在检查事务
--- 软件包 gcc.x86_64.0.4.8.5-4.el7 将被 安装
-- 正在处理依赖关系 libgomp = 4.8.5-4.el7,它被软件包 gcc-4.8.5-4.el7.x86_64 需要
-- 正在处理依赖关系 cpp = 4.8.5-4.el7,它被软件包 gcc-4.8.5-4.el7.x86_64 需要
-- 正在处理依赖关系 glibc-devel ;= 2.2.90-12,它被软件包 gcc-4.8.5-4.el7.x86_64 需要
-- 正在处理依赖关系 libmpfr.so.4()(64bit),它被软件包 gcc-4.8.5-4.el7.x86_64 需要
-- 正在处理依赖关系 libmpc.so.3()(64bit),它被软件包 gcc-4.8.5-4.el7.x86_64 需要
-- 正在处理依赖关系 libgomp.so.1()(64bit),它被软件包 gcc-4.8.5-4.el7.x86_64 需要
-- 正在检查事务
--- 软件包 cpp.x86_64.0.4.8.5-4.el7 将被 安装
--- 软件包 glibc-devel.x86_64.0.2.17-106.el7_2.8 将被 安装
-- 正在处理依赖关系 glibc-headers = 2.17-106.el7_2.8,它被软件包 glibc-devel-2.17-106.el7_2.8.x86_64 需要
-- 正在处理依赖关系 glibc-headers,它被软件包 glibc-devel-2.17-106.el7_2.8.x86_64 需要
--- 软件包 libgomp.x86_64.0.4.8.5-4.el7 将被 安装
--- 软件包 libmpc.x86_64.0.1.0.1-3.el7 将被 安装
--- 软件包 mpfr.x86_64.0.3.1.1-4.el7 将被 安装
-- 正在检查事务
--- 软件包 glibc-headers.x86_64.0.2.17-106.el7_2.8 将被 安装
-- 正在处理依赖关系 kernel-headers = 2.2.1,它被软件包 glibc-headers-2.17-106.el7_2.8.x86_64 需要
-- 正在处理依赖关系 kernel-headers,它被软件包 glibc-headers-2.17-106.el7_2.8.x86_64 需要
-- 解决依赖关系完成
错误:软件包:glibc-headers-2.17-106.el7_2.8.x86_64 (updates)
需要:kernel-headers = 2.2.1
错误:软件包:glibc-headers-2.17-106.el7_2.8.x86_64 (updates)
需要:kernel-headers
您可以尝试添加 --skip-broken 选项来解决该问题
您可以尝试执行:rpm -Va --nofiles --nodigest

系统版本信息:

root@localhost:/# cat /etc/redhat-release $$ uname -r
CentOS Linux release 7.2.1511 (Core)
2.6.32-042stab113.11

在https://wiki.openvz.org/Download/kernel找到了合适的kernel-header


wget http://download.openvz.org/kernel/branches/rhel6-2.6.32/042stab113.11/vzkernel-headers-2.6.32-042stab113.11.x86_64.rpm

rpm -ivh vzkernel-headers-2.6.32-042stab113.11.x86_64.rpm

再安装gcc就可以了

实用功能:

1.参数说明:

htop命令参数选项

htop –d 数据刷新时间

htop –u aurain 显示用户aurain的所属进程

M    按Memory 使用排序

P    按CPU 使用排序

T    按Time+ 使用排序

F3 按进程名搜索

直接输入数字 光标将定位于该PID的进程

q 退出

进程内参数

PID:进程标志号,是非零正整数

USER:进程所有者的用户名

PR:进程的优先级别

NI:进程的优先级别数值

VIRT:虚拟内存virtual memory usage。一个应用占有的地址空间,只是要应用程序要求的,就全算在这里,而不管它真的用了没有。

RES:常驻内存resident memory usage。这个值就是该应用程序真正使用的内存,但还有两个小问题,一是有些东西可能放在交换盘上了(SWAP),二是有些内存可能是共享的。

SHR:shared memory。共享内存。就是说这一块内存空间有可能也被其他应用程序使用着;而Virt - Shr似乎就是这个程序所要求的并且没有共享的内存空间。

S:进程的状态,其中S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值是负数

%CPU:该进程占用的CPU使用率

%MEM:该进程占用的物理内存和总内存的百分比

TIME+:该进程启动后占用的总的CPU时间

COMMAND:进程启动的启动命令名称

2.隐藏重复进程

按F2→ 选择Display options→选择 Hide userland threads

 

很多人遇到过服务器RAID5挂掉,往往掉一个盘后,第二个盘也立刻挂掉。

大家都知道RAID5 一次允许一个盘缺失,

RAID 5也是以数据的校验位来保证数据的安全,但它不是以单独硬盘来存放数据的校验位,而是将数据段的校验位交互存放于各个硬盘上。这样,任何一个硬盘损坏,都可以根据其它硬盘上的校验位来重建损坏的数据。硬盘的利用率为n-1。

如果挂掉两个盘,数据就玩完了。
理论上两个硬盘同时失效的概率是很低的,但为什么会这样呢?

从数学角度说,每个磁盘的平均无故障时间 (MTBF) 大约为 50 万至 150 万小时(也就是每 50~150 年发生一次硬盘损坏)。实际往往不能达到这种理想的情况,在大多数散热和机械条件下,都会造成硬盘正常工作的时间大幅减少。考虑到每个磁盘的寿命不同,阵列中的任何磁盘都可能出现问题,从统计学角度说,阵列中 N 个磁盘发生故障的机率比单个磁盘发生故障的机率要大 N 倍。结合上述因素,如果阵列中的磁盘数量合理,且这些磁盘的平均无故障时间 (MTBF) 较短,那么在磁盘阵列的预期使用寿命过程中,就很有可能发生磁盘故障(比方说每几个月或每隔几年就会发生一次故障)。

两块磁盘同时损坏的几率有多大呢(“同时”就是指一块磁盘尚未完全修复时另一块磁盘也坏掉了)?如果说 RAID 5 阵列的MTBF相当于MTBF^2,那么这种几率为每隔10^15个小时发生一次(也就是1万多年才出现一次),因此不管工作条件如何,发生这种情况的概率是极低的。从数学理论角度来说,是有这种概率,但在现实情况中我们并不用考虑这一问题。不过有时却是会发生两块磁盘同时损坏的情况,我们不能完全忽略这种可能性,实际两块磁盘同时损坏的原因与MTBF基本没有任何关系。

今天刚好在测试一个ZFS阵列,能清晰地进行数据校验并看到结果,于是正好分析了一下原因。

对这种情况来说,这里首先要引入一个一般人不常接触到的概念:

BER 硬盘误码率,英文是BER(Bit Error Rate),是描述硬盘性能的一个非常重要的参数,是衡量硬盘出错可能性的一个参数。

这个参数代表你写入硬盘的数据,在读取时遇到 不可修复的读错误的概率。

(不能恢复的ECC读取错误)从统计角度来说也比较少见,一般来说是指读取多少位后会出现一次读取错误。

随着硬盘容量增加,驱动器读取数据的误读率就会增加,而硬盘容量暴涨,误码率的比例一直保持相对增加。一个1TB的驱动器是需要更多读取整个驱动器,这是在RAID重建期间发生错误的概率会比300G 驱动器遇到错误的几率大。
那这个错误的几率到底有多大呢?或者说,我们写入多少GB数据,才会遇到1byte的读取错误呢?

看这篇文章:
http://lenciel.cn/docs/scsi-sata-reliability/

对于不同类型的硬盘(以前企业级、服务器、数据中心级硬盘用SCSI/光纤,商用、民用级别是IDE;现在对应的则是SAS/SATA;
他们的MRBF(平均无故障时间)是接近的,但是BER便宜的SATA硬盘要比昂贵的SCSI硬盘的误码率(BER)要高得多。
也就是说,出现某个sector无法读取的情况,SATA要比SCSI严重得多。
这两种硬盘(企业级的SCSI/ FC/ SAS 磁盘)/(商用/民用级的IDE/SATA)BER的差距大概是1-2个数量级。

按照文中的计算,一个1TB的硬盘,通常你无法读取所有sector的概率达到了56%,因此你用便宜的大容量SATA盘,在出现硬盘故障的情况下重建RAID的希望是:无法实现。

我们回到RAID5的情况来。
在RAID5大行其道之初,硬盘的容量基本不超过100GB.

在过去,做RAID5一般RAID的磁盘容量都不大,比如72GB。无法恢复一个RAID的概率按照文献是1.1%(注意,1.1%已经很不错了,因为你在硬盘故障之后,才需要去恢复RAID。两个概率是要相乘的。

当硬盘容量上升到200GB,假设出现故障的概率是线性增长的[1]。那么失败率有11%,估计负责存储的人就被老板操的厉害了。

但是56%,也就是你用1TB的SATA硬盘做RAID5的话,当你遇到一个硬盘失效的情况,几乎剩下的两个以上硬盘(RAID5最少组合是3个)铁定会遇到一个硬盘读取错误,从而重建失败。

所以,以前小硬盘做RAID5,基本很少遇到同时挂掉两个盘的情况;现在硬盘大了,出问题的概率也越来越大了。

有人会问:56%?
文章里面这个数据还是显得有些“不可信”。大概是因为下面两个原因,我们才没有怎么听说过这么高的BER吧。

首先,我们自己用的硬盘都不会跑RAID。虽然现在我们自己的硬盘容量也变得很大(现在主流台式机SATA硬盘应该就是500G),但是这个量级的硬盘上,你往往不会把500G硬盘全部写满;而大多数数据你都很少去读取它。因此从概率上讲,坏道出现在那些没卵味的电影和音乐上的可能性大很多:大多数电影和音乐都没卵味。

但是对于跑RAID的用户,对整个硬盘进行读取的事情经常发生。即使系统足够和谐,知道不对你报告那些出现在你从不读取的文件中的坏道,但是也只是略过了报告这一步:它还是会找到所有的坏道,56%就来了。

其次,虽然你丢了一些sector,一般情况下也没啥关系。还是以电影和音乐为例,大多数的压缩算法都从设计上允许有一些这样或者那样的误码。丢了几个sector的数据,也许对你来说就是松岛枫身上一些无名的马赛克而已,你都不知道是硬盘作祟。

现在还有所谓的监控专用企业级SATA,其原理就是在固件上做手脚,让硬盘即使遇到写入的数据读取错误,也不管三七二十一直接跳过,不再重试读取(标准硬盘的读取方式是遇到某个扇区CRC错误自动重新再去读,直到读到正确的数据为止)。这对监控数据来说是理所当然的(大多数监控的硬盘都是在不停地写入,但是很少需要读取),除非遇到出现问题需要重现影像时。
遇到这种情况概率是很低地,我手头的数十个十六路硬盘摄像机,镜头也过百个,基本上几个月才需要用到回放一次,而即使需要回放,也只需要其中的很小一部分数据(比如某几个摄像头,某一天中一个小时的录像)。
但是拿这种硬盘来做RAID5就更糟糕了,当RAID5重建需要数据百分百正确时,你压根不可能读到正确的数据。

我们继续来看今天的测试数据:
我用FreeBSD 的RAIDZ软阵列创建了一个6X1TB硬盘的RAID5。当然,我没有硬盘损坏,这六个硬盘都是好的;
但是我们不管这个,这里用RAIDZ的原因是RAIDZ有数据巡检(scrub)功能,然后又能直观地看到数据巡检的结果。
一般的硬件阵列卡,也就是插在主板PCI/PCIX/PCIE/或者主板集成的RAID5,压根就没这项功能;
企业级的数据存储,也只有到盘阵级别(比如IBM DS3000/4000/5000,DELL MD3000….etc)才有这类功能,但是你也看不到检查的结果,最多能在日志里看到某个硬盘CRC失败,然后跳红灯掉出来,阵列柜告警通知你换硬盘。你别想知道这个硬盘到底是彻底挂了呢,还是有读取错误,还是有坏道。。。总之两眼一抹黑。
ZFS的好处之一就在这里了:你在命令行打个 zpool scrub tank (tank就是你创建的raid的名字),它就开工忠实地开始巡检整个阵列了,读取上面的每个字节数据,并与当初写入时的md5值进行比较,发现错误的话就报告,并尝试用冗余数据修复。这个过程是后台进行的,并且用户可以直观地看到巡检的进度、速度/所需时间以及结果。

1|  scan: scrub in progress since Tue Jan 10 16:19:26 2012
2|       4.67T scanned out of 5.02T at 332M/s, 0h18m to go
3|        620K repaired, 92.88% done
4|config:
5|
6|        NAME             STATE     READ WRITE CKSUM
7|        ftp              ONLINE       0     0     0
8|          raidz1-0       ONLINE       0     0     0
9|            mfisyspd0p3  ONLINE       0     0     3  (repairing)
            mfisyspd5p3  ONLINE       0     0     6  (repairing)
            mfisyspd1p3  ONLINE       0     0     2  (repairing)
            mfisyspd4p3  ONLINE       0     0     8  (repairing)
            mfisyspd2p3  ONLINE       0     0     2  (repairing)
            mfisyspd3p3  ONLINE       0     0     3  (repairing)

errors: No known data errors

哦,我来解释一下上面的数据的意思。为了方便起见,我在前面编了1-9行号。
第二行,数据量/阵列容量,剩余时间。因为是测试,我非常BT地把阵列几乎塞满了数据;
第三行:读取错误数据量//巡检进度;

7,8,就是阵列状态,
第9行以后是6个硬盘的编号和状态。
大家要注意的是第9行开始以后6行的最后一列,也就是提示repairing括号前的CKSUM数据。
看到墨有?有墨有?有墨有?

每个硬盘都出现了数量不等的读取错误,最少两个盘各两个;最多一个盘8个。

OK。经过整整四个多小时的扫描后,我们的阵列数据修复了620K。
这些数据才刚写进去没过多久,最早的数据也没有超过一周。

scan: scrub repaired 620K in 4h25m with 0 errors on Tue Jan 10 20:45:12 2012
config:

        NAME             STATE     READ WRITE CKSUM
        ftp              ONLINE       0     0     0
          raidz1-0       ONLINE       0     0     0
            mfisyspd0p3  ONLINE       0     0     3
            mfisyspd5p3  ONLINE       0     0     6
            mfisyspd1p3  ONLINE       0     0     2
            mfisyspd4p3  ONLINE       0     0     8
            mfisyspd2p3  ONLINE       0     0     2
            mfisyspd3p3  ONLINE       0     0     3

但是这个修复的原因是RAID5,并且每个硬盘都是好的状态,有提供足够的CRC冗余。

你别小看这620K——当你的RAID5挂掉了一个盘(根据MTBF原理,你如果有50个硬盘,每年都可能损坏至少一个);

这620K数据就是致命的了:
剩下的5个硬盘,已经无法提供足够的CRC校验数据;除非每个字节都能被顺利读取,否则这个RAID5算是废了,
只要有1个扇区错误,你就算用一个全新的硬盘替换掉那个挂掉的硬盘,也无法顺利重建RAID5。
对于市面上常见的阵列卡,直接的后果就是,在用热备盘重建时,或者甚至尚未开始重建
(RAID5没有热备又没有及时发现硬盘挂掉,或者手头、仓库没有冷备盘,采购途中等)RAID5带病运行时,
需要读取数据,偏偏又很不巧读到那个该死的BER扇区,于是BER扇区所在的硬盘直接跳掉。。。又红了。。。。。

嗯嗯,以上数据已经解释了RAID5往往一次挂两个的原因——不是用户RP问题,从BER 角度来说,是硬盘其实早坏鸟,我们没发现而已。当某个硬盘因为MTBF原因整个挂掉,有问题的BER 扇区开始跳出来作梗,于是RAID5就完蛋鸟。

我们也能总结遇到RAID5一次挂掉俩盘的概率:

1. 使用越大容量的硬盘做RAID5,遇到BER 扇区的概率越大;比如用100G硬盘做RAID5就比用1TB的安全;
2. 使用越多盘数的硬盘做RAID5,遇到BER 扇区的概率越大;比如用3个盘做的RAID5,比6个盘做的RAID5安全;
3. 使用越便宜的硬盘做RAID5,遇到BER 扇区的概率越大;比如用SCSI/FC/SAS盘比用IDE/SATA的RAID5安全;
4. RAID5里面存放的数据越多,塞得越满,遇到BER 扇区的概率越大;比如存了100G数据的比存了1TB数据的RAID5安全;

第四条同时也要看阵列卡,某些卡REBUID时只读取存过数据的扇区,某些卡则不管三七二十一要读完整个盘。

从数据角度来说,ZFS软阵列此时有它独特的优势:即使存在BER扇区,它也能跳过坏扇区继续读取其他数据,从而将损失控制在最小范围内(仅仅是BER扇区所在的文件有问题,而不会整个阵列挂掉)

比如这个例子:

scan: scrub repaired 0 in 9h0m with 4768 errors on Thu Sep 8 08:23:00 2011
config:

NAME STATE READ WRITE CKSUM
ftp ONLINE 0 0 39
da2 ONLINE 0 0 156

errors: Permanent errors have been detected in the following files:

ftp:<0x7ef04>
ftp:<0x7ef11>
ftp:<0x7ef12>
ftp:<0x7ee1a>
ftp:<0x7ef31>
ftp:<0x7ef42>
ftp:<0x7ee57>
ftp:<0x7ef5e>
ftp:<0x7ef6d>
ftp:<0x7ee70>
ftp:<0x7ee71>
ftp:<0x7ef71>
ftp:<0x7ee87>

10TB的分区,巡检后发现156个错误,但是损失仅仅是13个文件。
而且能指出这13个文件的位置及文件名,并且这13个文件也不是完全不能读取,仅仅是某些字节损坏而已。

也许这13个文件中有些是影音、图像,损失几个字节无伤大雅;也许是其他地方另有备份,可以重新复制过来;也许是某些系统文件,只需重装软件或系统即可恢复,总之,用了zfs 后损失可以控制在能容忍的范围内,这就是zfs软件阵列的优势了。

顺便鼓吹一下,zpool scrub 命令可以定期执行哦,比如每隔1-2周的周六晚上开始运行,自动检查并修复错误。这种数据自动巡检功能我从来没有在任何插卡式或者板载阵列卡上见到过,只有阵列柜级别的存储设备上才有,而且巡检报告也没有精确到文件级别这种程度。

如果用了硬件阵列卡,这个就悲剧了。。。。啥都没有。


 

OK,原因已经分析了,经验也总结过了,
最后一节:怎么做?

我是下载狂,一定要要放很多数据,数据量以TB计,即将突破三位数;
又是穷人,花不起很多钱,只能用最便宜的SATA盘,最好是最便宜又大碗的西数绿盘;
技术有差距啊,折腾不起ZFS;
胆子又小,担惊受怕不起,看完这篇文章,想到自己RAID里的数据随时会全部莫有,晚上睡觉都睡不着,伤不起啊肿摸办?

解决方案1. 对于不重要的大量数据,比如可以下载来的影音数据,不要做阵列。直接用单盘,每个盘放一批数据。

数据量大到一定程度,目前来说凡是总量在2TB以上的SATA阵列,如果你做了RAID5,不仅数据没保障,万一坏掉一个盘,你有50%以上的概率同时掉第二个盘,那是一定毛都不剩一根。
运气好的话,可以通过让第二个挂掉的硬盘强行上线的方式勉强恢复阵列运行,你也必须有同等容量的空间让你腾挪数据;
不要说这个数据量的备用空间一般不会有,就算有,来回折腾一次所需要耗费的时间足够让你一个礼拜没个安耽觉睡。
有人说不会啊,我这个RAID5读取有300MB/s呢,2TB数据只要两个小时。
那是你平时——RAID5缺盘运行时,性能大概只有平时的1/10-1/20,外加上肯定有读不过去的文件需要跳过。。。。再加上读不过去会掉盘,
又要重启重新强制上线——这样的事件还不止一次,按照前面的测试,6个1T盘一共遇到24个读取错误,也就是你备份的进度得熄火24次——这些事儿堆一块儿,如果不是一个心理素质非常好的,处理过N起类似事件经验的数据中心老油子,对于第一次遇到这种情况的新手绝对是噩梦般的经历。

解决方案2. 做RAID1阵列。对于重要的、并且经常变动更新数据,比如财务数据、照片、文档资料,建议用RAID1。
RAID1多花了一个盘,但是多了一道保障。

解决方案3:光磁介质冷备份。通常我们叫做刻盘,呵呵。或者硬盘冷备——我两个硬盘各复制一份,拔掉一个硬盘放抽屉里,最适合照片之类数据。

解决方案4:RAID6。不过这个需要高级别的RAID卡支持,这个卡通常会很贵,至少贵出1-2个1TB盘的价值;
同等容量还要多加一个硬盘,个人觉得在6个硬盘以内,相对RAID1的方案没有优势。既没有经济优势,又没有性能优势——啥都没有,不如老老实实做RAID1。
优点当然有咯:即使遇到挂一个盘,它还算是一个RAID5——性能没有大减,数据也还有冗余,我慢慢等硬盘保修回来即可。
注意哦,6个1T以上盘。也就是说,你的硬盘总容量少于这个数字,还是不用考虑RAID6了。

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth

# append to the history file, don't overwrite it
shopt -s histappend

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar

# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
    xterm-color|*-256color) color_prompt=yes;;
esac

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
	# We have color support; assume it's compliant with Ecma-48
	# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
	# a case would tend to support setf rather than setaf.)
	color_prompt=yes
    else
	color_prompt=
    fi
fi

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac

# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
    #alias dir='dir --color=auto'
    #alias vdir='vdir --color=auto'

    alias grep='grep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias egrep='egrep --color=auto'
fi

# colored GCC warnings and errors
export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'

# some more ls aliases
alias ll='ls -alhF'
alias la='ls -A'
alias l='ls -CF'

# Add an "alert" alias for long running commands.  Use like so:
#   sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'

# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
  if [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi

#给history记录添加上时间戳
export HISTTIMEFORMAT="%F %T "

#set time style
export TIME_STYLE='+%Y-%m-%d %H:%M:%S'