leadscloud

Google SEO|外贸营销推广

将 170w行的txt文件.按行把数据导入到数据库中.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
header ( "Content-type: text/html;charset=utf-8" ); 
set_time_limit(0);
include('Database.class.php');
$db = new Database('127.0.0.1', 'root', 'root', 'test'); //数据库
$fp = fopen('171w.txt', 'r'); //文件
$i=1; //开始行数
$array = array(); //用来存放从XXX-XXX行的数据的数组
//回调函数
function callback($now) {
global $db, $array, $i, $fp;
if(empty($array)) { //为了节省资源..我们只生成一次数组
while (!feof($fp)) {
if($i == $now) { //循环到需要读取的行数时
for($j=$i;$j<=$i+999;$j++) { //读取下面的1000行并存储到数组中
$array[$j] = stream_get_line($fp, 1000000, "\n");
}
break;
}
stream_get_line($fp, 1000000, "\n"); //实践证明 stream_get_line 比 fgets 快很多..
$i++;
}
}
$db->insert("INSERT INTO test(name) VALUES('{$array[$now]}')"); //插入到数据库中
}
include('SkiyoProcess.class.php');
$sp = new SkiyoProcess(2, 1000, 171000); //间隔为2秒 每次插入1000条数据 一共171000行数据
$sp->process('callback');

原文:http://blogread.cn/it/article/1825?f=wb

这篇文章来源于Quroa的一个问答《What are some time-saving tips that every Linux user should know?》—— Linux用户有哪些应该知道的提高效率的技巧。我觉得挺好的,总结得比较好,把其转过来,并加了一些自己的理解。 首先,我想告诉大家,在Unix/Linux下,最有效率技巧的不是操作图形界面,而是命令行操作,因为命令行意味着自动化。如果你看过《你可能不知道的Shell》以及《28个Unix/Linux的命令行神器》你就会知道Linux有多强大,这个强大完全来自于命令行,于是,就算你不知道怎么去做一个环保主义的程序员,至少他们可以让你少熬点夜,从而有利于你的身体健康和性生活。下面是一个有点长的列表,正如作者所说,你并不需要知道所有的这些东西,但是如果你还在很沉重地在使用Linux的话,这些东西都值得你看一看。 (注:如果你想知道下面涉及到的命令的更多的用法,你一定要man一点。对于一些命令,你可以需要先yum或apt-get来安装一下,如果有什么问题,别忘了Google。如果你要Baidu的话,我仅代表这个地球上所有的生物包括微生物甚至细菌病毒和小强BS你到宇宙毁灭)

基础

  • **学习 Bash **。你可以man bash来看看bash的东西,并不复杂也并不长。你用别的shell也行,但是bash是很强大的并且也是系统默认的。(学习zsh或tsch只会让你在很多情况下受到限制)

  • 学习 vim 。在Linux下,基本没有什么可与之竞争的编辑器(就算你是一个Emacs或Eclipse的重度用户)。你可以看看《简明vim攻略》和 《Vim的冒险游戏》以及《给程序员的Vim速查卡》还有《把Vim变成一个编程的IDE》等等。

  • 了解 ssh。明白不需要口令的用户认证(通过ssh-agent, ssh-add),学会用ssh翻墙,用scp而不是ftp传文件,等等。你知道吗?scp 远端的时候,你可以按tab键来查看远端的目录和文件(当然,需要无口令的用户认证),这都是bash的功劳。
     

  • 熟悉bash的作业管理,如: &, Ctrl-Z, Ctrl-C, jobs, fg, bg, kill, 等等。当然,你也要知道Ctrl+\(SIGQUIT)和Ctrl+C (SIGINT)的区别。

  • 简单的文件管理 : ls 和 ls -l (你最好知道 “ls -l” 的每一列的意思), less, head, tail 和 tail -f, ln 和 ln -s (你知道明白hard link和soft link的不同和优缺点), chown, chmod, du (如果你想看看磁盘的大小 du -sk *), df, mount。当然,原作者忘了find命令。

  • 基础的网络管理: ip 或 ifconfig, dig。当然,原作者还忘了如netstat, ping, traceroute, 等

  • 理解正则表达式,还有grep/egrep的各种选项。比如: -o, -A, 和 -B 这些选项是很值得了解的。

  • 学习使用 apt-get 和 yum 来查找和安装软件(前者的经典分发包是Ubuntu,后者的经典分发包是Redhat),我还建议你试着从源码编译安装软件。
    日常

  • 在 bash 里,使用 Ctrl-R 而不是上下光标键来查找历史命令。

  • 在 bash里,使用 Ctrl-W 来删除最后一个单词,使用 Ctrl-U 来删除一行。请man bash后查找Readline Key Bindings一节来看看bash的默认热键,比如:Alt-. 把上一次命令的最后一个参数打出来,而Alt-* 则列出你可以输入的命令。

  • 回到上一次的工作目录: cd –  (回到home是 cd ~)

  • 使用 xargs。这是一个很强大的命令。你可以使用-L来限定有多少个命令,也可以用-P来指定并行的进程数。如果你不知道你的命令会变成什么样,你可以使用xargs echo来看看会是什么样。当然, -I{} 也很好用。示例:

    1
    2
    3
    `find` `. -name \*.py | ``xargs` `grep` `some_function`
    `cat` `hosts | ``xargs` `-I{} ``ssh` `root@{} ``hostname`
  • pstree -p 可以帮你显示进程树。(读过我的那篇《一个fork的面试题》的人应该都不陌生)

  • 使用 pgrep 和 pkill 来找到或是kill 某个名字的进程。 (-f 选项很有用).

  • 了解可以发给进程的信号。例如:要挂起一个进程,使用 kill -STOP [pid]. 使用 man 7 signal 来查看各种信号,使用kill -l 来查看数字和信号的对应表

  • 使用 nohup 或  disown 如果你要让某个进程运行在后台。

  • 使用netstat -lntp来看看有侦听在网络某端口的进程。当然,也可以使用 lsof。

  • 在bash的脚本中,你可以使用 set -x 来debug输出。使用 set -e 来当有错误发生的时候abort执行。考虑使用 set -o pipefail 来限制错误。还可以使用trap来截获信号(如截获ctrl+c)。

  • 在bash 脚本中,subshells (写在圆括号里的) 是一个很方便的方式来组合一些命令。一个常用的例子是临时地到另一个目录中,例如:

    1
    2
    3
    `# do something in current dir`
    `(``cd` `/some/other/dir``; other-``command``)`
    `# continue in original dir`
  • 在 bash 中,注意那里有很多的变量展开。如:检查一个变量是否存在: ${name:?error message}。如果一个bash的脚本需要一个参数,也许就是这样一个表达式 input_file=${1:?usage: $0 input_file}。一个计算表达式: i=$(( (i + 1) % 5 ))。一个序列: {1..10}。 截断一个字符串: ${var%suffix} 和 ${var#prefix}。 示例: if var=foo.pdf, then echo ${var%.pdf}.txt prints “foo.txt”.

  • 通过 <(some command) 可以把某命令当成一个文件。示例:比较一个本地文件和远程文件 /etc/hosts: diff /etc/hosts <(ssh somehost cat /etc/hosts)

  • 了解什么叫 “here documents” ,就是诸如 cat <<EOF 这样的东西。

  • 在 bash中,使用重定向到标准输出和标准错误。如: some-command >logfile 2>&1。另外,要确认某命令没有把某个打开了的文件句柄重定向给标准输入,最佳实践是加上 “</dev/null”,把/dev/null重定向到标准输入。

  • 使用 man ascii 来查看 ASCII 表。

  • 在远端的 ssh 会话里,使用 screen 或 dtach 来保存你的会话。(参看《28个Unix/Linux的命令行神器》)

  • 要来debug Web,试试curl 和 curl -I 或是 wget 。我觉得debug Web的利器是firebug,curl和wget是用来抓网页的,呵呵。

  • 把 HTML 转成文本: lynx -dump -stdin

  • 如果你要处理XML,使用 xmlstarlet

  • 对于 Amazon S3, s3cmd 是一个很方便的命令(还有点不成熟)

  • 在 ssh中,知道怎么来使用ssh隧道。通过 -L or -D (还有-R) ,翻墙神器。

  • 你还可以对你的ssh 做点优化。比如,.ssh/config 包含着一些配置:避免链接被丢弃,链接新的host时不需要确认,转发认证,以前使用压缩(如果你要使用scp传文件):

    1
    2
    3
    4
    5
    6
    `TCPKeepAlive=``yes`
    `ServerAliveInterval=15`
    `ServerAliveCountMax=6`
    `StrictHostKeyChecking=no`
    `Compression=``yes`
    `ForwardAgent=``yes`
  • 如果你有输了个命令行,但是你改变注意了,但你又不想删除它,因为你要在历史命令中找到它,但你也不想执行它。那么,你可以按下 Alt-# ,于是这个命令关就被加了一个#字符,于是就被注释掉了。
    **数据处理 **

  • 了解 sort 和 uniq 命令 (包括 uniq 的 -u 和 -d 选项).

  • 了解用 cut, paste, 和 join 命令来操作文本文件。很多人忘了在cut前使用join。

  • 如果你知道怎么用sort/uniq来做集合交集、并集、差集能很大地促进你的工作效率。假设有两个文本文件a和b已解被 uniq了,那么,用sort/uniq会是最快的方式,无论这两个文件有多大(sort不会被内存所限,你甚至可以使用-T选项,如果你的/tmp目录很小)

    1
    2
    3
    4
    5
    `cat` `a b | ``sort` `| ``uniq` `> c   ``# c is a union b 并集`
    `cat` `a b | ``sort` `| ``uniq` `-d > c   ``# c is a intersect b 交集`
    `cat` `a b b | ``sort` `| ``uniq` `-u > c   ``# c is set difference a - b 差集`
  • 了解和字符集相关的命令行工具,包括排序和性能。很多的Linux安装程序都会设置LANG 或是其它和字符集相关的环境变量。这些东西可能会让一些命令(如:sort)的执行性能慢N多倍(注:就算是你用UTF-8编码文本文件,你也可以很安全地使用ASCII来对其排序)。如果你想Disable那个i18n 并使用传统的基于byte的排序方法,那就设置export LC_ALL=C (实际上,你可以把其放在 .bashrc)。如果这设置这个变量,你的sort命令很有可能会是错的。

  • 了解 awk 和 sed,并用他们来做一些简单的数据修改操作。例如:求第三列的数字之和: awk ‘{ x += $3 } END { print x }’。这可能会比Python快3倍,并比Python的代码少三倍。

  • 使用 shuf 来打乱一个文件中的行或是选择文件中一个随机的行。

  • 了解sort命令的选项。了解key是什么(-t和-k)。具体说来,你可以使用-k1,1来对第一列排序,-k1来对全行排序。

  • Stable sort (sort -s) 会很有用。例如:如果你要想对两例排序,先是以第二列,然后再以第一列,那么你可以这样: sort -k1,1 | sort -s -k2,2

  • 我们知道,在bash命令行下,Tab键是用来做目录文件自动完成的事的。但是如果你想输入一个Tab字符(比如:你想在sort -t选项后输入<tab>字符),你可以先按Ctrl-V,然后再按Tab键,就可以输入<tab>字符了。当然,你也可以使用$’\t’。

  • 如果你想查看二进制文件,你可以使用hd命令(在CentOS下是hexdump命令),如果你想编译二进制文件,你可以使用bvi命令(http://bvi.sourceforge.net/ 墙)

  • 另外,对于二进制文件,你可以使用strings(配合grep等)来查看二进制中的文本。

  • 对于文本文件转码,你可以试一下 iconv。或是试试更强的 uconv 命令(这个命令支持更高级的Unicode编码)

  • 如果你要分隔一个大文件,你可以使用split命令(split by size)和csplit命令(split by a pattern)。
    系统调试

  • 如果你想知道磁盘、CPU、或网络状态,你可以使用 iostat, netstat, top (或更好的 htop), 还有 dstat 命令。你可以很快地知道你的系统发生了什么事。关于这方面的命令,还有iftop, iotop等(参看《28个Unix/Linux的命令行神器》)

  • 要了解内存的状态,你可以使用free和vmstat命令。具体来说,你需要注意 “cached” 的值,这个值是Linux内核占用的内存。还有free的值。

  • Java 系统监控有一个小的技巧是,你可以使用kill -3 <pid> 发一个SIGQUIT的信号给JVM,可以把堆栈信息(包括垃圾回收的信息)dump到stderr/logs。

  • 使用 mtr 会比使用 traceroute 要更容易定位一个网络问题。

  • 如果你要找到哪个socket或进程在使用网络带宽,你可以使用 iftop 或 nethogs。

  • Apache的一个叫 ab 的工具是一个很有用的,用quick-and-dirty的方式来测试网站服务器的性能负载的工作。如果你需要更为复杂的测试,你可以试试 siege。

  • 如果你要抓网络包的话,试试 wireshark 或 tshark。

  • 了解 strace 和 ltrace。这两个命令可以让你查看进程的系统调用,这有助于你分析进程的hang在哪了,怎么crash和failed的。你还可以用其来做性能profile,使用 -c 选项,你可以使用-p选项来attach上任意一个进程。

  • 了解用ldd命令来检查相关的动态链接库。注意:ldd的安全问题

  • 使用gdb来调试一个正在运行的进程或分析core dump文件。参看我写的《GDB中应该知道的几个调试方法

  • 学会到 /proc 目录中查看信息。这是一个Linux内核运行时记录的整个操作系统的运行统计和信息,比如: /proc/cpuinfo, /proc/xxx/cwd, /proc/xxx/exe, /proc/xxx/fd/, /proc/xxx/smaps.

  • 如果你调试某个东西为什么出错时,sar命令会有用。它可以让你看看 CPU, 内存, 网络, 等的统计信息。

  • 使用 dmesg 来查看一些硬件或驱动程序的信息或问题。
    作者最后加了一个免责声明:Disclaimer: Just because you can do something in bash, doesn’t necessarily mean you should. ;) (全文完)

http://coolshell.cn/articles/8883.html

下面是Kristóf Kovács收集的28个Unix/Linux下的28个命令行下的工具(原文链接),有一些是大家熟悉的,有一些是非常有用的,有一些是不为人知的。这些工具都非常不错,希望每个人都知道。本篇文章还在Hacker News上被讨论,你可以过去看看。我以作者的原文中加入了官网链接和一些说明。

dstat & sar

iostat, vmstat, ifstat 三合一的工具,用来查看系统性能(我在《性能调优攻略》中提到过那三个xxstat工具)。

官方网站:http://dag.wieers.com/rpm/packages/dstat/

你可以这样使用:

alias dstat=``'dstat -cdlmnpsy'

dstat screenshot

slurm

查看网络流量的一个工具

官方网站:_  Simple Linux Utility for Resource Management_

slurm screenshot

vim & emacs

真正程序员的代码编辑器。

vim screenshot

screen, dtach, tmux, byobu

你是不是经常需要 SSH 或者 telent 远程登录到 Linux 服务器?你是不是经常为一些长时间运行的任务而头疼,比如系统备份、ftp 传输等等。通常情况下我们都是为每一个这样的任务开一个远程终端窗口,因为他们执行的时间太长了。必须等待它执行完毕,在此期间可不能关掉窗口或者断开连接,否则这个任务就会被杀掉,一切半途而废了。

Screen是一个可以在多个进程之间多路复用一个物理终端的窗口管理器。Screen中有会话的概念,用户可以在一个screen会话中创建多个screen窗口,在每一个screen窗口中就像操作一个真实的telnet/SSH连接窗口那样。请参看IBM DeveloperWorks的这篇文章《使用 screen 管理你的远程会话

gnu screen screenshot

dtach 是用来模拟screen的detach的功能的小工具,其可以让你随意地attach到各种会话上 。下图为dtach+dvtm的样子。

**tmux**是一个优秀的终端复用软件,类似GNU Screen,但来自于OpenBSD,采用BSD授权。使用它最直观的好处就是,通过一个终端登录远程主机并运行tmux后,在其中可以开启多个控制台而无需再“浪费”多余的终端来连接这台远程主机;当然其功能远不止于此。与screen相比的优点:可以横向和纵向分割窗口,且窗格可以自由移动和调整大小。可在多个缓冲区进行复制和粘贴,支持跨窗口搜索;非正常断线后不需重新detach;……  有人说——与tmux相比,screen简直弱爆了

byobu是Ubuntu开发的,在Screen的基础上进行包装,使其更加易用的一个工具。最新的Byobu,已经是基于Tmux作为后端了。可通过“byobu-tmux”这个命令行前端来接受各种与tmux一模一样的参数来控制它。Byobu的细节做的非常好,效果图如下:

multitail

MultiTail是个用来实现同时监控多个文档、类似tail命令的功能的软件。他和tail的区别就是他会在控制台中打开多个窗口,这样使同时监控多个日志文档成为可能。他还可以看log文件的统计,合并log文件,过滤log文件,分屏,……。

官网:http://www.vanheusden.com/multitail/

multitail screenshot

tpp

终端下的PPT,要是在某某大会上用这个演示PPT,就太TMD的Geek了。

官网:http://www.ngolde.de/tpp.html

tpp screenshot

xargs & parallel

Executes tasks from input (even multithread).

xargs 是一个比较古老的命令,有简单的并行功能,这个不说了。对于GNU parallel ( online manpage )来说,它不仅能够处理本机上多执行绪,还能分散至远端电脑协助处理。而使用GNU parallel前,要先确定本机有安装GNU parallel / ssh / rsync,远端电脑也要安装ssh。

xargs screenshot

duplicity & rsyncrypto

Duplicity是使用rsync算法加密的高效率备份软件,Duplicity支持目录加密生产和格式上传到远程或本地文件服务器。

rsyncrypto 就是 rsync + encryption。对于rsync的算法可参看酷壳的rsync核心算法

Encrypting backup tools.

duplicity screenshot

nethack & slash’em

NetHackWiki),20年历史的古老电脑游戏。没有声音,没有漂亮的界面,不过这个游戏真的很有意思。网上有个家伙说:如果你一生只做一件事情,那么玩NetHack。这句话很惹眼,但也让人觉得这个游戏很复杂不容易上手。其实,这个游戏很虽然很复杂,却容易上手。虽然玩通关很难,但上手很容易。NetHack上有许多复杂的规则,”the DevTeam thinks of everything”(开发团队想到了所有的事情)。各种各样的怪物,各种各样的武器….,有许多spoilers文件来说明其规则。除了每次开始随机生成的地图,每次玩游戏,你也都会碰到奇怪的事情: 因为喝了一种药水,变成了机器人;因为踢坏了商店的门被要求高价赔偿;你的狗为你偷来了商店的东西….. 这有点象人生,你不能完全了解这个世界,但你仍然可以选择自己的面对方式。

网上有许多文章所这是最好的电脑游戏或最好的电脑游戏之一。也许是因为它开放的源代码让人赞赏,古老的历史让人宽容,复杂的规则让人敬畏。虽然它不是当前流行的游戏,但它比任何一个当前流行的游戏都更有可能再经受20年的考验。

Slash’EM 也是一个基于NetHack的经典游戏。

nethack screenshot

lftp

利用lftp命令行ftp工具进行网站数据的增量备份,镜像,就像使用rsync一样。

lftp screenshot

ack

ack是一个perl脚本,是grep的一个可选替换品。其可以对匹配字符有高亮显示。是为程序员专门设计的,默认递归搜索,省提供多种文件类型供选。

ack screenshot

calcurse & remind + wyrd

calcurse是一个命令行下的日历和日程软件。remind + wyrd也很类似。关于日历,我不得不提一个Linux的Cycle日历,也是一个神器,呵呵。

calcurse screenshot

newsbeuter & rsstail

newsbeuter 和 rsstail 是命令行下RSS的阅读工具。

newsbeuter screenshot

powertop

做个环保的程序员,看看自己的电脑里哪些程序费电。PowerTOP 是一个让 Intel 平台的笔记本电脑节省电源的 Linux 工具。此工具由 Intel 公司发布。它可以帮助用户找出那些耗电量大的程序,通过修复或者关闭那些应用程序或进程,从而为用户节省电源。

powertop screenshot

htop & iotop

htop 和 iotop  用来查看进程,内存和IO负载。

htop screenshot

ttyrec & ipbt

ttyrec 是一个 tty 控制台录制程序,其所录制的数据文件可以使用与之配套的 ttyplay 播放。不管是你在 tty 中的各种操作,还是在 tty 中耳熟能详的软件,都可进行录制。

ipbt 是一个用来回放 ttyrec 所录制的控制台输入过程的工具。

与此类似的还有Shelr 和 termrec 

ipbt screenshot

rsync

通过SSH进行文件同步的经典工具(核心算法

rsync screenshot

mtr

MTR – traceroute 2.0,其是把 traceroute 和 ping 集成在一块的一个小工具 用于诊断网络。

mtr screenshot

socat & netpipes

socat是一个多功能的网络工具,名字来由是” Socket CAT”,可以看作是netcat的N倍加强版。

netpipes 和socat一样,主要是用来在命令行来进行socket操作的命令,这样你就可以在Shell脚本下行进socket网络通讯了。

socat screenshot

iftop & iptraf

iftopiptraf可以用来查看当前网络链接的一些流量情况。

iftop screenshot

siege & tsung

Siege是一个压力测试和评测工具,设计用于WEB开发这评估应用在压力下的承受能力:可以根据配置对一个WEB站点进行多用户的并发访问,记录每个用户所有请求过程的相应时间,并在一定数量的并发访问下重复进行。

Tsung 是一个压力测试工具,可以测试包括HTTP, WebDAV, PostgreSQL, MySQL, LDAP, and XMPP/Jabber等服务器。针对 HTTP 测试,Tsung 支持 HTTP 1.0/1.1 ,包含一个代理模式的会话记录、支持 GET、POST 和 PUT 以及 DELETE 方法,支持 Cookie 和基本的 WWW 认证,同时还支持 SSL。

参看:十个免费的Web压力测试工具

siege screenshot

ledger

ledger 一个命令行下记帐的小工具。

ledger screenshot

taskwarrior

TaskWarrior 是一个基于命令行的 TODO 列表管理工具。主要功能包括:标签、彩色表格输出、报表和图形、大量的命令、底层API、多用户文件锁等功能。

taskwarrior screenshot

下图是TaskWarrior 2.0的界面:

curl

cURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行。它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具。cURL还包含了用于程序开发的libcurl。cURL支援的通訊協定有FTP、FTPS、HTTP、HTTPS、TFTP、SFTP、Gopher、SCP、Telnet、DICT、FILE、LDAP、LDAPS、IMAP、POP3、SMTP和RTSP。

curl screenshot

rtorrent & aria2

rTorrent 是一个非常简洁、优秀、非常轻量的BT客户端. 它使用了 ncurses 库以 C++ 编写, 因此它完全基于文本并在终端中运行. 将 rTorrent 用在安装有 GNU Screen 和 Secure Shell 的低端系统上作为远程的 BT 客户端是非常理想的。

aria2 是 Linux 下一个不错的高速下载工具。由于它具有分段下载引擎,所以支持从多个地址或者从一个地址的多个连接来下载同一个文件。这样自然就大大加快了文件的下载速度。aria2 也具有断点续传功能,这使你随时能够恢复已经中断的文件下载。除了支持一般的 http(s) 和 ftp 协议外,aria2 还支持 BitTorrent 协议。这意味着,你也可以使用 aria2 来下载 torrent 文件。

 rtorrent screenshot

ttytter & earthquake

TTYtter 是一个Perl写的命令行上发Twitter的工具,可以进行所有其他平台客户端能进行的事情,当然,支持中文。脚本控、CLI控、终端控、Perl控的最愛。

Earthquake也是一个命令行上的Twitter客户端。

ttytter screenshot

vifm & ranger

Vifm 基于ncurses的文件管理器,DOS风格,用键盘操作。

vifm screenshot

Ranger用 Python 完成,默认为使用 Vim 风格的按键绑定,比如 hjkl(上下左右),dd(剪切),yy(复制)等等。功能很全,扩展/可配置性也非常不错。类似MacOS X下Finder(文件管理器)的多列文件管理方式。支持多标签页。实时预览文本文件和目录。

cowsay & sl

cowsay  不说了,如下所示,哈哈哈。还有xcowsay,你可以自己搜一搜。

cowsay screenshot

sl是什么?ls?,呵呵,你会经常把ls 打成sl吗?如果是的话,这个东西可以让你娱乐一下,你会看到一辆火车呼啸而过~~,相当拉风。你可以使用sudo apt-get install sl 安装。

最后,再介绍一个命令中linuxlogo,你可以使用 sudo apt-get install linuxlogo来安装,然后,就可以使用linuxlogo -L
来看一下各种Linux的logo了

(全文完)

http://coolshell.cn/articles/7829.html

看到这个标题大家一定会想到这篇神文《How Browsers Work》,这篇文章把浏览器的很多细节讲得很细,而且也被翻译成了中文。为什么我还想写一篇呢?因为两个原因,

1)这篇文章太长了,阅读成本太大,不能一口气读完。

2)花了大力气读了这篇文章后可以了解很多,但似乎对工作没什么帮助。

所以,我准备写下这篇文章来解决上述两个问题。希望你能在上班途中,或是坐马桶时就能读完,并能从中学会一些能用在工作上的东西。

浏览器工作大流程

废话少说,先来看个图:

从上面这个图中,我们可以看到那么几个事:

 

1)浏览器会解析三个东西:

  • 一个是HTML/SVG/XHTML,事实上,Webkit有三个C++的类对应这三类文档。解析这三种文件会产生一个DOM Tree。

  • CSS,解析CSS会产生CSS规则树。

  • Javascript,脚本,主要是通过DOM API和CSSOM API来操作DOM Tree和CSS Rule Tree.
    2)解析完成后,浏览器引擎会通过DOM Tree 和 CSS Rule Tree 来构造 Rendering Tree。注意:

  • Rendering Tree 渲染树并不等同于DOM树,因为一些像Header或display:none的东西就没必要放在渲染树中了。

  • CSS 的 Rule Tree主要是为了完成匹配并把CSS Rule附加上Rendering Tree上的每个Element。也就是DOM结点。也就是所谓的Frame。

  • 然后,计算每个Frame(也就是每个Element)的位置,这又叫layout和reflow过程。
    3)最后通过调用操作系统Native GUI的API绘制。

DOM解析

HTML的DOM Tree解析如下:

1
2
3
4
5
6
7
8
9
10
11
12
<html>
<html>
<head>
<title>Web page parsing</title>
</head>
<body>
<div>
<h1>Web page parsing</h1>
<p>This is an example Web page.</p>
</div>
</body>
</html>

上面这段HTML会解析成这样:

下面是另一个有SVG标签的情况。

CSS解析

CSS的解析大概是下面这个样子(下面主要说的是Gecko也就是Firefox的玩法),假设我们有下面的HTML文档:

1
2
3
4
5
6
7
8
9
<doc>
<title>A few quotes</title>
<para>
Franklin said that <quote>"A penny saved is a penny earned."</quote>
</para>
<para>
FDR said <quote>"We have nothing to fear but <span>fear itself.</span>"</quote>
</para>
</doc>

于是DOM Tree是这个样子:

然后我们的CSS文档是这样的:

1
2
3
4
/* rule 1 */ doc { display: block; text-indent: 1em; }
/* rule 2 */ title { display: block; font-size: 3em; }
/* rule 3 */ para { display: block; }
/* rule 4 */ [class="emph"] { font-style: italic; }

于是我们的CSS Rule Tree会是这个样子:

注意,图中的第4条规则出现了两次,一次是独立的,一次是在规则3的子结点。所以,我们可以知道,建立CSS Rule Tree是需要比照着DOM Tree来的。CSS匹配DOM Tree主要是从右到左解析CSS的Selector,好多人以为这个事会比较快,其实并不一定。关键还看我们的CSS的Selector怎么写了。

注意:CSS匹配HTML元素是一个相当复杂和有性能问题的事情。所以,你就会在N多地方看到很多人都告诉你,DOM树要小,CSS尽量用id和class,千万不要过渡层叠下去,……

通过这两个树,我们可以得到一个叫Style Context Tree,也就是下面这样(把CSS Rule结点Attach到DOM Tree上):

所以,Firefox基本上来说是通过CSS 解析 生成 CSS Rule Tree,然后,通过比对DOM生成Style Context Tree,然后Firefox通过把Style Context Tree和其Render Tree(Frame Tree)关联上,就完成了。注意:Render Tree会把一些不可见的结点去除掉。而Firefox中所谓的Frame就是一个DOM结点,不要被其名字所迷惑了

注:Webkit不像Firefox要用两个树来干这个,Webkit也有Style对象,它直接把这个Style对象存在了相应的DOM结点上了。

渲染

渲染的流程基本上如下(黄色的四个步骤):

  1. 计算CSS样式
  2. 构建Render Tree
  3. Layout – 定位坐标和大小,是否换行,各种position, overflow, z-index属性 ……
  4. 正式开画

注意:上图流程中有很多连接线,这表示了Javascript动态修改了DOM属性或是CSS属会导致重新Layout,有些改变不会,就是那些指到天上的箭头,比如,修改后的CSS rule没有被匹配到,等。

这里重要要说两个概念,一个是Reflow,另一个是Repaint。这两个不是一回事。

ul>

  • Repaint——屏幕的一部分要重画,比如某个CSS的背景色变了。但是元素的几何尺寸没有变。
  • Reflow——意味着元件的几何尺寸变了,我们需要重新验证并计算Render Tree。是Render Tree的一部分或全部发生了变化。这就是Reflow,或是Layout。(HTML使用的是flow based layout,也就是流式布局,所以,如果某元件的几何尺寸发生了变化,需要重新布局,也就叫reflow)reflow 会从这个root frame开始递归往下,依次计算所有的结点几何尺寸和位置,在reflow过程中,可能会增加一些frame,比如一个文本字符串必需被包装起来。
    下面是一个打开Wikipedia时的Layout/reflow的视频(注:HTML在初始化的时候也会做一次reflow,叫 intial reflow),你可以感受一下:

 

Reflow的成本比Repaint的成本高得多的多。DOM Tree里的每个结点都会有reflow方法,一个结点的reflow很有可能导致子结点,甚至父点以及同级结点的reflow。**在一些高性能的电脑上也许还没什么,但是如果reflow发生在手机上,那么这个过程是非常痛苦和耗电的**。

 

所以,下面这些动作有很大可能会是成本比较高的。

  • 当你增加、删除、修改DOM结点时,会导致Reflow或Repaint
  • 当你移动DOM的位置,或是搞个动画的时候。
  • 当你修改CSS样式的时候。
  • 当你Resize窗口的时候(移动端没有这个问题),或是滚动的时候。
  • 当你修改网页的默认字体时。

注:display:none会触发reflow,而visibility:hidden只会触发repaint,因为没有发现位置变化。

多说两句关于滚屏的事,通常来说,如果在滚屏的时候,我们的页面上的所有的像素都会跟着滚动,那么性能上没什么问题,因为我们的显卡对于这种把全屏像素往上往下移的算法是很快。但是如果你有一个fixed的背景图,或是有些Element不跟着滚动,有些Elment是动画,那么这个滚动的动作对于浏览器来说会是相当相当痛苦的一个过程。你可以看到很多这样的网页在滚动的时候性能有多差。因为滚屏也有可能会造成reflow。

基本上来说,reflow有如下的几个原因:

  • Initial。网页初始化的时候。
  • Incremental。一些Javascript在操作DOM Tree时。
  • Resize。其些元件的尺寸变了。
  • StyleChange。如果CSS的属性发生变化了。
  • Dirty。几个Incremental的reflow发生在同一个frame的子树上。

好了,我们来看一个示例吧:

1
2
3
4
5
6
7
8
9
10
11
12
var bstyle = document.body.style; // cache

bstyle.padding = "20px"; // reflow, repaint
bstyle.border = "10px solid red"; // 再一次的 reflow 和 repaint

bstyle.color = "blue"; // repaint
bstyle.backgroundColor = "#fad"; // repaint

bstyle.fontSize = "2em"; // reflow, repaint

// new DOM element - reflow, repaint
document.body.appendChild(document.createTextNode('dude!'));

当然,我们的浏览器是聪明的,它不会像上面那样,你每改一次样式,它就reflow或repaint一次。一般来说,浏览器会把这样的操作积攒一批,然后做一次reflow,这又叫异步reflow或增量异步reflow。但是有些情况浏览器是不会这么做的,比如:resize窗口,改变了页面默认的字体,等。对于这些操作,浏览器会马上进行reflow。

但是有些时候,我们的脚本会阻止浏览器这么干,比如:如果我们请求下面的一些DOM值:

  1. offsetTop, offsetLeft, offsetWidth, offsetHeight
  2. scrollTop/Left/Width/Height
  3. clientTop/Left/Width/Height
  4. IE中的 getComputedStyle(), 或 currentStyle

因为,如果我们的程序需要这些值,那么浏览器需要返回最新的值,而这样一样会flush出去一些样式的改变,从而造成频繁的reflow/repaint。

减少reflow/repaint

下面是一些Best Practices:

1)不要一条一条地修改DOM的样式。与其这样,还不如预先定义好css的class,然后修改DOM的className。

1
2
3
4
5
6
7
8
9
10
11
// bad
var left = 10,
top = 10;
el.style.left = left + "px";
el.style.top = top + "px";

// Good
el.className += " theclassname";

// Good
el.style.cssText += "; left: " + left + "px; top: " + top + "px;";

2)把DOM离线后修改。如:

  • 使用documentFragment 对象在内存里操作DOM
  • 先把DOM给display:none(有一次reflow),然后你想怎么改就怎么改。比如修改100次,然后再把他显示出来。
  • clone一个DOM结点到内存里,然后想怎么改就怎么改,改完后,和在线的那个的交换一下。
    3)**不要把DOM结点的属性值放在一个循环里当成循环里的变量。**不然这会导致大量地读写这个结点的属性。

4)尽可能的修改层级比较低的DOM。当然,改变层级比较底的DOM有可能会造成大面积的reflow,但是也可能影响范围很小。

5)为动画的HTML元件使用fixed或absoult的position,那么修改他们的CSS是不会reflow的。

6)千万不要使用table布局。因为可能很小的一个小改动会造成整个table的重新布局。

In this manner, the user agent can begin to lay out the table once the entire first row has been received. Cells in subsequent rows do not affect column widths. Any cell that has content that overflows uses the ‘overflow’ property to determine whether to clip the overflow content.

Fixed layout, CSS 2.1 Specification
This algorithm may be inefficient since it requires the user agent to have access to all the content in the table before determining the final layout and may demand more than one pass.

Automatic layout, CSS 2.1 Specification

几个工具和几篇文章

有时候,你会也许会发现在IE下,你不知道你修改了什么东西,结果CPU一下子就上去了到100%,然后过了好几秒钟repaint/reflow才完成,这种事情以IE的年代时经常发生。所以,我们需要一些工具帮我们看看我们的代码里有没有什么不合适的东西。

参考

原文:http://coolshell.cn/articles/9666.html

最近浏览器在保存图片或上传文件时经常崩溃, 个人猜测是因为windows资源管理器的问题, 一直无法解决,今天能过windows的事件查看器,看到以下错误,在网上搜索,果然发现有类似问题, 其实不是浏览器的问题, 以前经常是搜索chrome经常崩溃怎么办, 所以没的到解决办法.

Application Error

错误应用程序名称: chrome.exe,版本: 26.0.1410.64,时间戳: 0x5163bfb1
错误模块名称: shellext.dll_unloaded,版本: 0.0.0.0,时间戳: 0x50d2bf97
异常代码: 0xc0000005
错误偏移量: 0x11df83fa
错误进程 ID: 0x620
错误应用程序启动时间: 0x01ce67dd5bda0094
错误应用程序路径: C:\Program Files\Google\Chrome\Application\chrome.exe
错误模块路径: shellext.dll
报告 ID: 719d9e97-d420-11e2-9e59-50e5494efd95

问题出在 shellext.dll, 是软件桌面工具,http://www.wenjian.cn/xijie/shellext.dll.html .

根据这篇文章(http://blog.csdn.net/phoenix2121/article/details/8854501)确定是快用青苹果助手的问题. 把快用助手卸载掉就行了.

最初用Privoxy是因为七星庐的文章强大的代理调度器代理Privoxy,用作代理切换,后来顺便也用起它广告过滤的功能

能实现这两个功能的软件/插件很多,而且用起来往往比privoxy来的方便,比如foxproxy和adblock。我之所以用privoxy是因为以下原因:

  • 作为系统的全局自动代理切换器。GNOME和环境变量的代理设置不是对任何软件都管用,PAC也不是哪里都行
  • 广告过滤可用于任何浏览器,并且容易定制,改改网页什么的

配置是繁琐些,但用起来确实不错。

安装用源里的就可以,默认是作为系统服务启动的。装好后请将浏览器代理设置为127.0.0.1:8118,以便测试。地址栏输入”p.p”可以查看配置、文档、调试等等。

代理切换

配置文件都在/etc/privoxy目录下。编辑config文件,加入一行
actionsfile pac.action
这表示添加一个动作文件,文件名是pac.action。在同目录下建立文件”pac.action”,并写入配置。一个示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{{alias}}
direct = +forward-override{forward .}
ssh = +forward-override{forward-socks5 127.0.0.1:7000 .}
gae = +forward-override{forward 127.0.0.1:8000}
default = direct
#==========默认代理==========
{default}
/
#==========直接连接==========
{direct}
.edu.cn
202.117.255.
222.24.211.70
#==========SSH代理==========
{ssh}
.launchpad.net
#==========GAE代理==========
{gae}
.webupd8.org
222.24.211.70

上面的{{alias}}部分定义了一些缩写,注意http代理和socks代理的写法不同。

后面的如{direct}部分定义对哪些地址应用这个代理。其中”/“表示全部地址。注意一个URL的域名部分只能用glob匹配,而地址部分可以用复杂的正则表达式。具体可以看Privoxy的文档

这些规则在后面的会覆盖前面的,比如222.24.211.70实际是以gae代理访问的。这样可以实现一些稍微复杂的功能

广告过滤

广告过滤用的文件要多些,可能还需要filter文件。先看一个最基本的只使用action文件和block动作的广告过滤。直接编辑user.action文件,添加

1
2
3
{+block}
.5622.cn
/.*\.swf$

这样5622.cn和所有flash都被阻止了。如果你还想看某些flash视频,可以在后面再-block,这会覆盖前面的设置,如

1
2
{-block}
static.youku.com/.*\.swf$

配合filter文件和action文件,可以实现对网页内容的替换,从而屏蔽某些不想要的内容。先编辑config文件,去掉”filterfile user.filter”这行的注释,然后在同目录下建立user.filter文件,写入

1
2
3
4
FILTER: iframe
s@</head>@<style type="text/css">\n\
iframe {display:none; !important}\n\
</style>\n$0@

这样就定义了一个名为”iframe”的过滤器。之后再编辑user.action文件,添加

1
2
{+filter{iframe}}
.filestube.com

这表明对filestube应用”iframe”这个过滤器。filter书写复杂些

除了过滤广告,还能做做地址转向,比如

1
2
3
4
5
{+redirect{s@^http://[^/]*/.*?&amp;q=(.*)@http://www.google.com/search?hl=en&amp;q=$1@}}
.google.com.hk/search

{+redirect{s@^http://[^/]*(/$|$)@http://www.google.com/ncr@}}
.google.com.hk/$

其它内容

以普通用户启动

先关掉privoxy服务,可以用sysv-rc-conf或者直接删掉/etc/init.d/privoxy文件。然后将/etc/privoxy目录的内容复制到家目录下,比如~/.privoxy。编辑config文件,将”confdir /etc/privoxy”改为

confdir /home/用户名/.privoxy
然后用下面命令启动
privoxy --no-daemon $HOME/.privoxy/config

有身份验证的代理

先获得”用户名:密码”的base64编码,方法如下

1
perl -e "use MIME::Base64; print encode_base64('用户名:密码');"

然后这样写alias

1
proxy = +forward-override{forward 127.0.0.1:808} +add-header{Proxy-authorization: Basic <auth>}

<auth>替换为上面得到的base64编码的用户名和密码

一个完整的方案

上面这些文件完全可以精简和清晰,我的目录下只有config、pac.action、user.action、user.filter这四个文件。另外还可以小脚本来切换默认的代理。下面贴出这些配置和切换脚本,略加修改过的,我的配置目录是~/.proxy

切换脚本:http://paste.pocoo.org/show/372771/

这个脚本是,在家里默认代理(default)directgae之间切换,学校是在paper和gae之间切换。绑定个快捷键会很方便

人们总喜欢往HTML标签上添加自定义属性来存储和操作数据。但这样做的问题是,你不知道将来会不会有其它脚本把你的自定义属性给重置掉,此外,你这样做也会导致html语法上不符合Html规范,以及一些其它副作用。这就是为什么在HTML5规范里增加了一个自定义data属性,你可以拿它做很多有用的事情。

你可以去读一下HTML5的详细规范,但这个自定义data属性的用法非常的简单,就是你可以往HTML标签上添加任意以 “data-“开头的属性,这些属性页面上是不显示的,它不会影响到你的页面布局和风格,但它却是可读可写的。

下面的一个代码片段是一个有效的HTML5标记:

1
<div id="awesome" data-myid="3e4ae6c4e">Some awesome data</div>

可是,怎么来读取这些数据呢?你当然可以遍历页面元素来读取你想要的属性,但jquery已经内置了方法来操作这些属性。使用jQuery的.data()方法来访问这些”data-*” 属性。其中一个方法就是 .data(obj),这个方法是在 jQuery1.4.3版本后出现的,它能返回相应的data属性。

举个例子,你可以用下面的写法读取 data-myid属性值:

1
2
var myid= jQuery("#awesome").data('myid');
console.log(myid);

你还可以在”data-*” 属性里使用json语法,例如,如果你写出下面的html:

1
<div id="awesome-json" data-awesome='{"game":"on"}'></div>

你可以通过js直接访问这个数据,通过json的key值,你能得到相应的value:

1
2
var gameStatus= jQuery("#awesome-json").data('awesome').game;
console.log(gameStatus);

你也可以通过.data(key,value)方法直接给”data-“ 属性赋值。一个重要的你要注意的事情是,这些”data-“ 属性应该和它所在的元素有一定的关联,不要把它当成存放任意东西的存储工具。

译者补充:尽管”data-“ 是HTML5才出现的属性,但jquery是通用的,所以,在非HTML5的页面或浏览器里,你仍然可以使用.data(obj)方法来操作”data-“ 数据。

[英文原文:HTML 5 data-* attributes, how to use them and why ]

关于两者的区别,其实是很古老的问题。但是时至今日,由于各种网络误传以及一些不负责任的书籍误笔,仍然有相当多的人将伪类与伪元素混为一谈,甚至不乏很多CSS老手。早些年刚入行的时候,我自己也被深深误导,因为论坛里的帖子大多不关心这种概念的细微差别,即使有人出来说一句:“这两个是不同的”,也只是被更多的帖子淹没掉而已。所以觉得有必要写下这些我所知的部分,这里着重写的是为什么这两者不同,以及一些平时容易错过的细节。

无论是伪类还是伪元素,都属于CSS选择器的范畴。所以它们的定义可以在CSS标准的选择器章节找到。分别是 CSS2.1 Selectors 和 CSS Selector Level 3,两者都已经是推荐标准。

标准的定义

在CSS2.1里,5.10 Pseudo-elements and pseudo-classes 描述了这两个概念的由来,它们是被一同提及的。但到了 Selector Level 3 里,它们就被分开到两个小节里加以区分。但无论如何,伪类和伪元素的引入都是因为在文档树里有些信息无法被充分描述,比如CSS没有“段落的第一行”之类的选择器,而这在一些出版场景里又是必须的。用标准里的话说:

CSS introduces the concepts of pseudo-elements and pseudo-classes to permit formatting based on information that lies outside the document tree.
简单翻译一下,就是:
CSS 引入伪类和伪元素的概念是为了实现基于文档树之外的信息的格式化
这么说很抽象,其实就是为了描述一些现有CSS无法描述的东西。缺少什么,则引入什么,不管是标准,还是人,都是如此成长而来。

伪类与伪元素的区别

这里我大可以列一个表格,把所有的伪类和伪元素分开罗列,但这未免太形式化,与其记住“哪些是哪些不是”,不如真正地加以区分。伪类和伪元素本身就有一个根本的不同之处,这点直接体现在了标准的描述语句上。

先看一个伪元素 first-line 例子。现在有一段HTML,内容是一个段落:

1
2
3
4
<p>I am the bone of my sword. Steel is my body, and fire is my blood. 
I have created over a thoustand blades.
Unknown to Death.Nor known to Life. Have withstood pain to create many weapon.
Yet, those hands will never hold anything. So as I pray, unlimited blade works.</p>

如果我要描述这个段落的第一行,在不用伪元素的情况下,我会怎么做?想来我一定要嵌套一层 span,然后加上类名:

1
2
3
4
<p><span class="first-line">I am the bone of my sword. Steel is my body, and fire is my blood. </span> 
I have created over a thoustand blades.
Unknown to Death.Nor known to Life. Have withstood pain to create many weapon.
Yet, those hands will never hold anything. So as I pray, unlimited blade works.</p>

再反观一个伪类 first-child 的例子,有一个简单的列表:

1
2
3
4
<ul>
<li></li>
<li></li>
</ul>

如果我要描述 ul 的第一个元素,我无须嵌套新的元素,我只须给第一个已经存在的 li 添加一个类名就可以了:

1
2
3
4
<ul>
<li class="first-child"></li>
<li></li>
</ul>

尽管,第一行第一个元素,这两者的语意相似,但最后作用的效果却完全不同。所以,伪类和伪元素的根本区别在于:它们是否创造了新的元素(抽象)。从我们模仿其意义的角度来看,如果需要添加新元素加以标识的,就是伪元素,反之,如果只需要在既有元素上添加类别的,就是伪类。而这也是为什么,标准精确地使用 “create” 一词来解释伪元素,而使用 “classify” 一词来解释伪类的原因。一个描述的是新创建出来的“幽灵”元素,另一个则是描述已经存在的符合“幽灵”类别的元素。

伪类一开始单单只是用来表示一些元素的动态状态,典型的就是链接的各个状态(LVHA)。随后CSS2标准扩展了其概念范围,使其成为了所有逻辑上存在但在文档树中却无须标识的“幽灵”分类。

伪元素则代表了某个元素的子元素,这个子元素虽然在逻辑上存在,但却并不实际存在于文档树中。

伪类和伪元素混淆的由来

最为混淆的,可能是大部分人都将 :before 和 :after 这样的伪元素随口叫做伪类,而且即使在概念混淆的情况下,实际使用上也毫无问题——因为即使概念混淆,对真正使用也不会造成多少麻烦:)

CSS Selector Level 3 为了区分这两者的混淆,而特意用冒号加以区分:

  • 伪类用一个冒号表示 :first-child
  • 伪元素则使用两个冒号表示 ::first-line
    并且规定,浏览器既要兼容CSS1和2里既存的伪元素的单冒号表示,同时又要不兼容CSS3新引入的伪元素的单冒号表示。后来的结果大家都知道,因为低版本IE对双冒号的兼容问题,几乎所有的CSSer在写样式的时候都不约而同的使用了单冒号。这无形中,让这种混淆延续了下来。而CSS3新伪元素的使用到目前为止,还远远不成气候。

伪类和伪元素使用上需要注意的地方

明白其不同之后,就需要注意和考虑在实际使用上的一些问题。比如:伪类和伪元素的选择器特殊性(优先级)如何计算?

我在之前的 CSS选择器距离无关 一文中,翻译过CSS标准的计算选择器的特殊性这一部分,看完那部分,答案就清楚了:除了否定伪类的特殊规定外,分开各自作为真正的类和元素计算

虽然标准以后的版本可能会允许选择器多伪元素的情况,但就目前为止,伪元素在一个选择器里只能出现一次,并且只能出现在末尾。实则,伪元素是选中了某个元素的符合逻辑的某个实际却不存在的部分,所以应用中也不会有人将其误写成多个。伪类则是像真正的类一样发挥着类的作用,没有数量上的限制,只要不是相互排斥的伪类,也可以同时使用在相同的元素上。关于CSS3选择器的详细解释,推荐 rogerjohansson 的 CSS 3 selectors explained

结束语

本来只是想稍稍写点,不想话又多了…到了最后,我一度觉得自己还漏了很多,不断在脑海里搜索,但可能只能下次在补充了。写这篇的目的是为下篇《CSS伪类与CSS伪元素的典型应用》做个铺垫,不想理论的东西一写自己就开始废话连篇了,惭愧…回看本篇,自己的思路跳的有些乱了,洋洋洒洒这么多字,可能概括起来没几句话,但如果希望尽可能表达清楚,则又免不了冗余过头。理论总是显得枯燥了些,下篇闲谈应用应该不至于这么沉闷:)

参考资料

  1. CSS2.1 Pseudo-elements and pseudo-classes from W3C
  2. Selectors Level 3 W3C Recommendation 29 September 2011 from W3C
  3. Difference between a pseudo-class and a pseudo-element by Laura L. Carlson
  4. THE DIFFERENCE BETWEEN PSEUDO-CLASSES AND PSEUDO-ELEMENTS by Stephan Muller

useradd -M -s /sbin/nologin -n username

passwd username

输入两次密码就行了,然后你就可以使用了。可以使用myentunnela或者BitviseSSHClient。

清明:

晴,天气相比前几天比较热。与同事去动物园玩玩,人人人人人人人人动物人人人人人人人人人人人。

没回家有点遗憾,不过后来证实回家也须更不好。

有些人与你的距离越来越远了。

那些逝去的人,今天会想起你们,曾经的岁月我们那样年轻。现在

目前的状态不是很好,,,

郑州动物园

[caption id=”attachment_313582” align=”aligncenter” width=”3264”]郑州动物园 郑州动物园[/caption]

0%