leadscloud

Google SEO|外贸营销推广

20140624143525
本文讲述如何免费申请SSL证书,并搭建https网站,由于服务器是NGINX,顺便会介绍如何安装SPDY协议。

StartSSL介绍

StartSSL是一家CA机构,它的根证书很久之前就被一些具有开源背景的浏览器支持(Firefox浏览器、谷歌Chrome浏览器、苹果Safari浏览器等)。
在今年9月份,StartSSL竟然搞定了微软:微软在升级补丁中,更新了通过Windows根证书认证程序(Windows Root Certificate Program)的厂商清单,并首次将StartCom公司列入了该认证清单,这是微软首次将提供免费数字验证技术的厂商加入根证书认证列表中。现在,在Windows 7或安装了升级补丁的Windows Vista或Windows XP操作系统中,系统会完全信任由StartCom这类免费数字认证机构认证的数字证书,从而使StartSSL也得到了IE浏览器的支持。

StartSSL申请注意事项

(1)需要一个域名,并开通域名邮箱,邮箱前缀为:webmaster这样的信息,一定要开通一个webmaster@yourdomainname.com这样的域名,这个会用来验证你的域名;
(2)申请时一定要填写完整正确的信息,否则无法通过申请,我就是因为第一次填写的地址信息不全,没有通过,一般添写正确的地址很快就会通过的;
(3)打开网站 在control panel / sign-up 注意填写正确资料。收到邮件后复制验证码。然后可以生成一个证书,注意,startssl.com不是以用户名、密码来验证用户的,是用证书来验证用户的。所以生成证书后(火狐会导入证书),注意备份证书。丢失证书后只能重新注册。
(4)登录后还要验证域名才能为该域名生成SSL证书,可以选择在whois里的邮箱、hostmaster@domain、postmaster@domain或者webmaster@domain
(5)然后就可以在Certificates wizard里就可以申请SSL证书了。
(6)有效期一年(到期前会收到邮件通知续期)。

申请流程

所有的资料都最好使用正确的。因为注册SSL是一件很严肃的事情。还有就是如果你的IP地址是在大陆,你输入香港也是会被拒绝的。而且你的地址也是也是要详细的。按照表单写完以后点击Continue按钮。然后你填写的邮箱会收到一个验证码。 上面说大概需要等6个小时收到通知,其实一般一两分钟就会出结果

打开你的邮箱,把验证码输入到你的浏览器Code的框里,然后继续。

通过后,会收到通过验证的邮件,然后给你一个URL,输入到浏览器中进行下一步安装证书。如果弹出的窗口依然还让你输入Code,那则输入邮件下面链接的Code。

点击Continue,接下来你的浏览器开始安装私钥,相当于建立用户名密码

然后密钥安装成功以后提示你开始安装证书。

证书安装完毕以后会祝贺你一下。点击完成。 这时给你会收到邮件说你安装好啦,可以使用了。

在Validations Wizard选择里验证你的域名。按照提示操作就行了,它会扫描你的网站上的邮箱,然后列出来,会给你的邮箱发一封信,所以你一定要有一个企业邮箱来收信的。域名验证成功后,接下来申请域名SSL证书。

点击Certificates Wizard ,选择下拉菜单中的Web Server SSL/TSL Certificate

然后进入下一步他会问你验证方式,这一步如果你跳过需要在VPS上设置,具体可以见网站:http://blog.nicky1605.com/the-free-ssl-configuration-startssl-on-nginx.html

如果没有跳过,你必须设置密码,不少于10位的。然后点击下一步生成一段字符串

这一小的操作中会出现两段字条串,一段类似这样的

1
2
3
4
5
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,1FBB7A12C5332861D52FEDFA2E3E7AE3

....

复制内容保存为 /etc/ssl/certs/xxxx.crt
一段类似这样的

1
2
3
-----BEGIN CERTIFICATE-----
MIIGdTCCBV2gAwIBAgIDYTrWMA0GCSqGSIc3FQEBBQUAMIGMMQswCQYDVQQGEwJJ
...

复制内容保存为 /etc/ssl/certs/xxxx.key

下面就是配置你的VPS上的NGINX服务器了。

vi /usr/local/nginx/conf/vhost/xxxx.conf

在Server里添加

1
2
3
4
5
6
7
8
listen 443 ssl spdy;
ssl on;
ssl_certificate /etc/ssl/certs/xxxx.crt;
ssl_certificate_key /etc/ssl/certs/xxxx.key;
ssl_session_timeout 10m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;

如果你想让http跳转到https下,需要再加一段代码

1
2
3
if ($ssl_protocol = "") {
rewrite ^/(.*)$ https://www.domain.com/$1 permanent;
}

如果出现循环重定向,检查下你的网站根目录下,是否有.htaccess文件,因为我的服务器是lnmpa的,apache的重定向文件还是会起作用的,检查下有无重定向到http的,一般是301重定向需要修改下。

上面这些做完之后,还需要另外对firefox浏览器作一些配置更改
/etc/ssl/certs/xxxx.crt所在目录执行以下代码

1
2
wget http://cert.startssl.com/certs/sub.class1.server.ca.pem
cat ca.pem sub.class1.server.ca.pem >> xxxx.crt

就是向 xxx.crt里面追加一些内容,这样firefox就不会提示证书不安全了。

下就是重启你的nginx服务器,但这里会提示你需要输入Enter PEM pass phrase
总不能每次重启都要输入那个密码吧,这个可以跳过的,方法按照我之前的一篇文章操作

/313864/lnmp%E4%B8%8Bnginx%E9%85%8D%E7%BD%AEssl%E5%AE%89%E5%85%A8%E8%AF%81%E4%B9%A6%E9%81%BF%E5%85%8D%E5%90%AF%E5%8A%A8%E8%BE%93%E5%85%A5enter-pem-pass-phrase/

SPDY协议安装

你要先下载最新的 OpenSSL,比如 1.0.1e,这里是下载列表,红色标注的就是最新版了。因为前些时间的openssl漏洞,现在linode好像自动已经升级到最新版1.0.1e了。

但还是需要下载,解压

1
2
3
cd /tmp
wget http://www.openssl.org/source/openssl-1.0.1e.tar.gz
tar zxvpf openssl-1.0.1e.tar.gz

然后下载最新的Nginx

先用 /usr/local/nginx/sbin/nginx -V 这个是查看nginx安装了什么模块 安装的时候把这些都再加上

1
2
3
4
5
6
7
8
9
wget http://nginx.org/download/nginx-1.7.2.tar.gz
tar zxvf nginx-1.7.2.tar.gz
cd nginx-1.7.2
./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-ipv6 --with-pcre --with-http_sub_module --with-http_spdy_module --with-openssl=/tmp/openssl-1.0.1e
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old
cp objs/nginx /usr/local/nginx/sbin/nginx
/usr/local/nginx/sbin/nginx -t
make upgrade
/usr/local/nginx/sbin/nginx -v

上面需要注意的是./configure --with-http_ssl_module --with-http_spdy_module --with-openssl=/tmp/openssl-1.0.1e 这是最小安装方法,你需要根据自己的配置安装,上面是lnmpa下面的。

--with-openssl=/tmp/openssl-1.0.1e 路径就是刚下载的那个路径。

再配置完成后,执行 /etc/init.d/nginx reload/usr/local/nginx/sbin/nginx -s reload 重载 Nginx 配置文件即可正常访问了。

如果你不想使用 SPDY ,记得修改Server里的 listen 443 ssl spdy; 改为 listen 443 ssl;

如何查看有没有启用SPDY成功没

在Chrome浏览器里打开 chrome://net-internals/#spdy 便能查看目前使用SPDY的连接。

或者使用插件查看, https://chrome.google.com/webstore/detail/spdy-indicator/mpbpobfflnpcgagjijhmgnchggcjblin

补充:关于 “此网页包含的脚本来自于身份未经验证的源” 的提示信息

出现这个一般是因为在网页内容中加载了其它不带https的内容,比如加载了google font,

1
<link href='http://fonts.googleapis.com/css?family=Antic+Slab' rel='stylesheet' type='text/css'>

一般解决办法就是把资源下载到本地,然后使用相对路径,或者使用https的资源地址。
google 支持https连接,上面的情况你可以直接改为

1
<link href='https://fonts.googleapis.com/css?family=Antic+Slab' rel='stylesheet' type='text/css'>

从Startssl免费申请到ssh证书后,把自己的一个网站搭建成了https网站。但是由于生成私钥key文件时输入了密码,导致每次重启nginx时都提示Enter PEM pass phrase , 这样会导致自己VPS上的重启脚本无法自动工作,每次都要人工重启。

在网上搜索后找到了解决办法。

在key的目录执行:openssl rsa -in server.key -out server.key.unsecure 然后在配置文件里使用unsecure这个文件名就行了

修改后的nginx配置如下:

1
2
3
4
5
6
7
8
9
10
# 这里是SSL的相关配置
server {
listen 443;
server_name www.example.com; # 你自己的域名
root /home/wwwroot/www.example.com;
ssl on;
ssl_certificate /etc/ssl/certs/server.crt;
# 修改下面这一行指向我们生成的server.key.unsecure文件
ssl_certificate_key /etc/ssl/certs/server.key.unsecure;
}

然后使用/etc/init.d/nginx restart重启Nginx.不提示便表示成功了。

背景

目前互联网上充斥着大量的关于RESTful API(为方便,下文中“RESTful API ”简写为“API”)如何设计的文章,然而却没有一个”万能“的设计标准:如何鉴权?API 格式如何?你的API是否应该加入版本信息?当你开始写一个app的时候,特别是后端模型部分已经写完的时候,你不得不殚精竭虑的设计和实现自己app的public API部分。因为一旦发布,对外发布的API将会很难改变。

在给SupportedFu设计API的时候,我试图以实用的角度来解决上面提到的问题。我希望可以设计出容易使用,容易部署,并且足够灵活的API,本文因此而生。

API设计的基本要求

网上的很多关于API设计的观点都十分”学院派“,它们也许更有理论基础,但是有时却和现实世界脱轨(因此我是自由派)。所以我这篇文章的目标是从实践的角度出发,给出当前网络应用的API设计最佳实践(当然,是我认为的最佳了~),如果觉得不合适,我不会遵从标准。当然作为设计的基础,几个必须的原则还是要遵守的:

  1. 当标准合理的时候遵守标准。
  2. API应该对程序员友好,并且在浏览器地址栏容易输入。
  3. API应该简单,直观,容易使用的同时优雅。
  4. API应该具有足够的灵活性来支持上层ui。
  5. API设计权衡上述几个原则。

需要强调的是:API的就是程序员的UI,和其他UI一样,你必须仔细考虑它的用户体验!

使用RESTful URLs 和action.

虽然前面我说没有一个万能的API设计标准。但确实有一个被普遍承认和遵守:RESTfu设计原则。它被Roy Felding提出(在他的”基于网络的软件架构“论文中第五章)。而REST的核心原则是将你的API拆分为逻辑上的资源。这些资源通过http被操作(GET ,POST,PUT,DELETE)。

那么我应该如何拆分出这些资源呢?

显然从API用户的角度来看,”资源“应该是个名词。即使你的内部数据模型和资源已经有了很好的对应,API设计的时候你仍然不需要把它们一对一的都暴露出来。这里的关键是隐藏内部资源,暴露必需的外部资源。

在SupportFu里,资源是 ticket、user、group。

一旦定义好了要暴露的资源,你可以定义资源上允许的操作,以及这些操作和你的API的对应关系:

1
2
3
4
5
*   GET /tickets # 获取ticket列表
* GET /tickets/12 # 查看某个具体的ticket
* POST /tickets # 新建一个ticket
* PUT /tickets/12 # 更新ticket 12.
* DELETE /tickets/12 #删除ticekt 12

可以看出使用REST的好处在于可以充分利用http的强大实现对资源的CURD功能。而这里你只需要一个endpoint:/tickets,再没有其他什么命名规则和url规则了,cool!

这个endpoint的单数复数

一个可以遵从的规则是:虽然看起来使用复数来描述某一个资源实例看起来别扭,但是统一所有的endpoint,使用复数使得你的URL更加规整。这让API使用者更加容易理解,对开发者来说也更容易实现。

如何处理关联?关于如何处理资源之间的管理REST原则也有相关的描述:

1
2
3
4
5
6
*   GET /tickets/12/messages- Retrieves list of messages for ticket #12
* GET /tickets/12/messages/5- Retrieves message #5 for ticket #12
* POST /tickets/12/messages- Creates a new message in ticket #12
* PUT /tickets/12/messages/5- Updates message #5 for ticket #12
* PATCH /tickets/12/messages/5- Partially updates message #5 for ticket #12
* DELETE /tickets/12/messages/5- Deletes message #5 for ticket #12

其中,如果这种关联和资源独立,那么我们可以在资源的输出表示中保存相应资源的endpoint。然后API的使用者就可以通过点击链接找到相关的资源。如果关联和资源联系紧密。资源的输出表示就应该直接保存相应资源信息。(例如这里如果message资源是独立存在的,那么上面 GET /tickets/12/messages就会返回相应message的链接;相反的如果message不独立存在,他和ticket依附存在,则上面的API调用返回直接返回message信息)

不符合CURD的操作

对这个令人困惑的问题,下面是一些解决方法:

  1. 重构你的行为action。当你的行为不需要参数的时候,你可以把active对应到activated这个资源,(更新使用patch).
  2. 以子资源对待。例如:github上,对一个gists加星操作:PUT /gists/:id/star 并且取消星操作:DELETE /gists/:id/star.
  3. 有时候action实在没有难以和某个资源对应上例如search。那就这么办吧。我认为API的使用者对于/search这种url也不会有太大意见的(毕竟他很容易理解)。只要注意在文档中写清楚就可以了。

永远使用SSL

毫无例外,永远都要使用SSL。你的应用不知道要被谁,以及什么情况访问。有些是安全的,有些不是。使用SSL可以减少鉴权的成本:你只需要一个简单的令牌(token)就可以鉴权了,而不是每次让用户对每次请求签名。

值得注意的是:不要让非SSL的url访问重定向到SSL的url。

文档

文档和API本身一样重要。文档应该容易找到,并且公开(把它们藏到pdf里面或者存到需要登录的地方都不太好)。文档应该有展示请求和输出的例子:或者以点击链接的方式或者通过curl的方式(请见openstack的文档)。如果有更新(特别是公开的API),应该及时更新文档。文档中应该有关于何时弃用某个API的时间表以及详情。使用邮件列表或者博客记录是好方法。

版本化

在API上加入版本信息可以有效的防止用户访问已经更新了的API,同时也能让不同主要版本之间平稳过渡。关于是否将版本信息放入url还是放入请求头有过争论:API version should be included in the URL or in a header. 学术界说它应该放到header里面去,但是如果放到url里面我们就可以跨版本的访问资源了。。(参考openstack)。

strip使用的方法就很好:它的url里面有主版本信息,同时请求头俩面有子版本信息。这样在子版本变化过程中url的稳定的。变化有时是不可避免的,关键是如何管理变化。完整的文档和合理的时间表都会使得API使用者使用的更加轻松。

结果过滤,排序,搜索:

url最好越简短越好,和结果过滤,排序,搜索相关的功能都应该通过参数实现(并且也很容易实现)。

**过滤:**为所有提供过滤功能的接口提供统一的参数。例如:你想限制get /tickets 的返回结果:只返回那些open状态的ticket–get /tickektsstate=open这里的state就是过滤参数。

**排序:**和过滤一样,一个好的排序参数应该能够描述排序规则,而不业务相关。复杂的排序规则应该通过组合实现:

1
2
*   GET /ticketssort=-priority- Retrieves a list of tickets in descending order of priority
* GET /ticketssort=-priority,created_at- Retrieves a list of tickets in descending order of priority. Within a specific priority, older tickets are ordered first

这里第二条查询中,排序规则有多个rule以逗号间隔组合而成。

**搜索:**有些时候简单的排序是不够的。我们可以使用搜索技术(ElasticSearch和Lucene)来实现(依旧可以作为url的参数)。

1
*   GET /ticketsq=return&amp;state=open&amp;sort=-priority,created_at- Retrieve the highest priority open tickets mentioning the word ‘return

对于经常使用的搜索查询,我们可以为他们设立别名,这样会让API更加优雅。例如:

1
get /ticketsq=recently_closed -> get /tickets/recently_closed.

限制API返回值的域

有时候API使用者不需要所有的结果,在进行横向限制的时候(例如值返回API结果的前十项)还应该可以进行纵向限制。并且这个功能能有效的提高网络带宽使用率和速度。可以使用fields查询参数来限制返回的域例如:

1
GET /ticketsfields=id,subject,customer_name,updated_at&amp;state=open&amp;sort=-updated_at

更新和创建操作应该返回资源

PUT、POST、PATCH 操作在对资源进行操作的时候常常有一些副作用:例如created_at,updated_at 时间戳。为了防止用户多次的API调用(为了进行此次的更新操作),我们应该会返回更新的资源(updated representation.)例如:在POST操作以后,返回201 created 状态码,并且包含一个指向新资源的url作为返回头

是否需要 “HATEOAS”

网上关于是否允许用户创建新的url有很大的异议(注意不是创建资源产生的url)。为此REST制定了HATEOAS来描述了和endpoint进行交互的时候,行为应该在资源的metadata返回值里面进行定义。

(译注:作者这里认为HATEOAS还不算成熟,我也不怎么理解这段就算了,读者感兴趣可以自己去原文查看)

只提供json作为返回格式

现在开始比较一下XML和json了。XML即冗长,难以阅读,又不适合各种编程语言解析。当然XML有扩展性的优势,但是如果你只是将它来对内部资源串行化,那么他的扩展优势也发挥不出来。很多应用(youtube,twitter,box)都已经开始抛弃XML了,我也不想多费口舌。给了google上的趋势图吧:

当然如果的你使用用户里面企业用户居多,那么可能需要支持XML。如果是这样的话你还有另外一个问题:你的http请求中的media类型是应该和accept 头同步还是和url?为了方便(browser explorability),应该是在url中(用户只要自己拼url就好了)。如果这样的话最好的方法是使用.xml或者.json的后缀。

命名方式?

是蛇形命令(下划线和小写)还是驼峰命名?如果使用json那么最好的应该是遵守JAVASCRIPT的命名方法-也就是说骆驼命名法。如果你正在使用多种语言写一个库,那么最好按照那些语言所推荐的,java,c#使用骆驼,python,ruby使用snake。

个人意见:我总觉得蛇形命令更好使一些,当然这没有什么理论的依据。有人说蛇形命名读起来更快,能达到20%,也不知道真假http://ieeexplore.ieee.org/xpl/articleDetails.jsptp=&arnumber=5521745

默认使用pretty print格式,使用gzip

只是使用空格的返回结果从浏览器上看总是觉得很恶心(一大坨有没有?~)。当然你可以提供url上的参数来控制使用“pretty print”,但是默认开启这个选项还是更加友好。格外的传输上的损失不会太大。相反你如果忘了使用gzip那么传输效率将会大大减少,损失大大增加。想象一个用户正在debug那么默认的输出就是可读的-而不用将结果拷贝到其他什么软件中在格式化-是想起来就很爽的事,不是么?

下面是一个例子:

1
2
3
4
$ curl https://API.github.com/users/veesahni > with-whitespace.txt
$ ruby -r json -e 'puts JSON JSON.parse(STDIN.read)' < with-whitespace.txt > without-whitespace.txt
$ gzip -c with-whitespace.txt > with-whitespace.txt.gz
$ gzip -c without-whitespace.txt > without-whitespace.txt.gz

输出如下:

1
2
3
4
*   without-whitespace.txt- 1252 bytes
* with-whitespace.txt- 1369 bytes
* without-whitespace.txt.gz- 496 bytes
* with-whitespace.txt.gz- 509 bytes

在上面的例子中,多余的空格使得结果大小多出了8.5%(没有使用gzip),相反只多出了2.6%。据说:twitter使用gzip之后它的streaming API传输减少了80%(link:https://dev.twitter.com/blog/announcing-gzip-compression-streaming-APIs).

只在需要的时候使用“envelope”

很多API象下面这样返回结果:

1
2
3
4
5
6
{
"data" : {
"id" : 123,
"name" : "John"
}
}

理由很简单:这样做可以很容易扩展返回结果,你可以加入一些分页信息,一些数据的元信息等-这对于那些不容易访问到返回头的API使用者来说确实有用,但是随着“标准”的发展(cors和http://tools.ietf.org/html/rfc5988#page-6都开始被加入到标准中了),我个人推荐不要那么做。

何时使用envelope?

有两种情况是应该使用envelope的。如果API使用者确实无法访问返回头,或者API需要支持交叉域请求(通过jsonp)。

jsonp请求在请求的url中包含了一个callback函数参数。如果给出了这个参数,那么API应该返回200,并且把真正的状态码放到返回值里面(包装在信封里),例如:

1
2
3
4
5
6
7
callback_function({
status_code: 200,
next_page: "https://..",
response: {
... actual JSON response body ...
}
})

同样为了支持无法方法返回头的API使用者,可以允许envelope=true这样的参数。

在post,put,patch上使用json作为输入

如果你认同我上面说的,那么你应该决定使用json作为所有的API输出格式,那么我们接下来考虑考虑API的输入数据格式。

很多的API使用url编码格式:就像是url查询参数的格式一样:单纯的键值对。这种方法简单有效,但是也有自己的问题:它没有数据类型的概念。这使得程序不得不根据字符串解析出布尔和整数,而且还没有层次结构–虽然有一些关于层次结构信息的约定存在可是和本身就支持层次结构的json比较一下还是不很好用。

当然如果API本身就很简单,那么使用url格式的输入没什么问题。但对于复杂的API你应该使用json。或者干脆统一使用json。

注意使用json传输的时候,要求请求头里面加入:Content-Type:application/json.,否则抛出415异常(unsupported media type)。

分页

分页数据可以放到“信封”里面,但随着标准的改进,现在我推荐将分页信息放到link header里面:http://tools.ietf.org/html/rfc5988#page-6。

使用link header的API应该返回一系列组合好了的url而不是让用户自己再去拼。这点在基于游标的分页中尤为重要。例如下面,来自github的文档

1
2
Link: <https://api.github.com/user/repos?page=3&amp;per_page=100>; rel="next", 
<https://api.github.com/user/repos?page=50&amp;per_page=100>; rel="last"

自动加载相关的资源

很多时候,自动加载相关资源非常有用,可以很大的提高效率。但是这却和RESTful的原则相背。为了如此,我们可以在url中添加参数:embed(或者expend)。embed可以是一个逗号分隔的串,例如:

1
GET /ticket/12embed=customer.name,assigned_user

对应的API返回值如下:

1
2
3
4
5
6
7
8
9
10
11
12
{
"id" : 12,
"subject" : "I have a question!",
"summary" : "Hi, ....",
"customer" : {
"name" : "Bob"
},
assigned_user: {
"id" : 42,
"name" : "Jim",
}
}

值得提醒的是,这个功能有时候会很复杂,并且可能导致N+1 SELECT 问题

重写HTTP方法

有的客户端只能发出简单的GET 和POST请求。为了照顾他们,我们可以重写HTTP请求。这里没有什么标准,但是一个普遍的方式是接受X-HTTP-Method-Override请求头。

速度限制

为了避免请求泛滥,给API设置速度限制很重要。为此 RFC 6585 引入了HTTP状态码429(too many requests)。加入速度设置之后,应该提示用户,至于如何提示标准上没有说明,不过流行的方法是使用HTTP的返回头。

下面是几个必须的返回头(依照twitter的命名规则):

1
2
3
*   X-Rate-Limit-Limit :当前时间段允许的并发请求数
* X-Rate-Limit-Remaining:当前时间段保留的请求数。
* X-Rate-Limit-Reset:当前时间段剩余秒数

为什么使用当前时间段剩余秒数而不是时间戳?

时间戳保存的信息很多,但是也包含了很多不必要的信息,用户只需要知道还剩几秒就可以再发请求了这样也避免了clock skew问题

有些API使用UNIX格式时间戳,我建议不要那么干。为什么?HTTP 已经规定了使用 RFC 1123 时间格式

鉴权 Authentication

restful API是无状态的也就是说用户请求的鉴权和cookie以及session无关,每一次请求都应该包含鉴权证明。

通过使用ssl我们可以不用每次都提供用户名和密码:我们可以给用户返回一个随机产生的token。这样可以极大的方便使用浏览器访问API的用户。这种方法适用于用户可以首先通过一次用户名-密码的验证并得到token,并且可以拷贝返回的token到以后的请求中。如果不方便,可以使用OAuth 2来进行token的安全传输。

支持jsonp的API需要额外的鉴权方法,因为jsonp请求无法发送普通的credential。这种情况下可以在查询url中添加参数:access_token。注意使用url参数的问题是:目前大部分的网络服务器都会讲query参数保存到服务器日志中,这可能会成为大的安全风险。

注意上面说到的只是三种传输token的方法,实际传输的token可能是一样的。

缓存

HTTP提供了自带的缓存框架。你需要做的是在返回的时候加入一些返回头信息,在接受输入的时候加入输入验证。基本两种方法:

**ETag:**当生成请求的时候,在HTTP头里面加入ETag,其中包含请求的校验和和哈希值,这个值和在输入变化的时候也应该变化。如果输入的HTTP请求包含IF-NONE-MATCH头以及一个ETag值,那么API应该返回304 not modified状态码,而不是常规的输出结果。

**Last-Modified:**和etag一样,只是多了一个时间戳。返回头里的Last-Modified:包含了 RFC 1123 时间戳,它和IF-MODIFIED-SINCE一致。HTTP规范里面有三种date格式,服务器应该都能处理。

出错处理

就像html错误页面能够显示错误信息一样,API 也应该能返回可读的错误信息–它应该和一般的资源格式一致。API应该始终返回相应的状态码,以反映服务器或者请求的状态。API的错误码可以分为两部分,400系列和500系列,400系列表明客户端错误:如错误的请求格式等。500系列表示服务器错误。API应该至少将所有的400系列的错误以json形式返回。如果可能500系列的错误也应该如此。json格式的错误应该包含以下信息:一个有用的错误信息,一个唯一的错误码,以及任何可能的详细错误描述。如下:

1
2
3
4
5
{
"code" : 1234,
"message" : "Something bad happened :-(",
"description" : "More details about the error here"
}

对PUT,POST,PATCH的输入的校验也应该返回相应的错误信息,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"code" : 1024,
"message" : "Validation Failed",
"errors" : [
{
"code" : 5432,
"field" : "first_name",
"message" : "First name cannot have fancy characters"
},
{
"code" : 5622,
"field" : "password",
"message" : "Password cannot be blank"
}
]
}

HTTP 状态码

1
2
3
4
5
6
7
8
9
10
11
12
200 ok  - 成功返回状态,对应,GET,PUT,PATCH,DELETE.
201 created - 成功创建。
304 not modified - HTTP缓存有效。
400 bad request - 请求格式错误。
401 unauthorized - 未授权。
403 forbidden - 鉴权成功,但是该用户没有权限。
404 not found - 请求的资源不存在
405 method not allowed - 该http方法不被允许。
410 gone - 这个url对应的资源现在不可用。
415 unsupported media type - 请求类型错误。
422 unprocessable entity - 校验错误时用。
429 too many request - 请求过多。

参考资料

原文链接:Vinay Sahni,编译:感谢@bruce-accumulate 的热心翻译

译文链接:http://blog.jobbole.com/41233/

Github Page绑定二级域名或者顶级域名,需要做两件事,一个是在github page下面创建 CNAME文件,一个就是设置你的DNS。

CNAME

创建一个CNAME文件,内容是你的域名,如:
domain.org
然后把此文件添加到Github仓库,上传到Github。Github服务器会设置domain.org为你的主域名,然后将www.domain.org和demo.github.com重定向到domain.org。

有一个在线的编辑器  http://prose.io/ 使用它可以在线修改你的github page,非常方便,适合不会使用命令的同学。

如果是想绑定二级域名,上面的设置还是不够的,比如你想把二级域名sub.domain.org 绑定到 demo.github.com ,你需要在CNAME文件里加上sub.demo.org

DNS

登陆你的域名管理界面。创建一条A记录,指向207.97.227.245这个IP地址。
sub.domain.org为博客域名,指向Github Page。
需要做的设置:

  • 创建CNAME文件,内容为sub.domain.org
  • 登陆域名管理,创建CNAME记录,sub -> demo.github.com

Github作免费空间有300M的空间限制 。

上周招聘了一个年轻人。面试的时候,很有热情,准备充分,对公司也做了研究,连对话提问,明显也是之前有所排练的,总而言之,看起来是一个做事很认真的小伙子。

他说:我觉得,这就是我想要的公司和文化,这就是我喜欢的工作!
这个小伙子戴着黑框眼镜,说这话的时候,一副理想主义者的激情神态。

坦白说,我被这种神态打动了。
我想,也许工作充满繁杂无聊,但只有这种激情,才能造就卓越。

后来我又看了一下作品,觉得底子不错。决定录用。
很快HR给他发了OFFER。第二周就来上班了。

几天后,他给主管发了一条短信,说自己不喜欢这个工作。发短信第二天,他就不来了。连离职手续都没办。

主管跟我说起时,我还很惊诧。“这不可能吧?”
我觉得这种轻率行为,完全不像是那个年轻人该有的。

我很想和他谈谈,给他发了条短信。没回复。我准备给他拨个电话,但转念一想,又觉得没这个必要。

就算打通电话了,我想跟他谈什么呢?

劝他继续来公司?——不,我不会再要他了。这样的年轻人,我也不敢要。
跟他谈什么是“责任”?——都是成年人,也挺没意思。
谈“喜欢”和“工作”的关系?——我不是稻盛和夫,我说不出“与其找喜欢的工作,不如喜欢上手头的工作”这种话。

想来想去,我想给他讲讲我自己的故事。

我想说说,7年前的自己。

那时我大学还没毕业,在一家影视广告公司做脚本文案。写脚本很辛苦,影视广告也并不有趣。跟我之前的想象完全不同。

恰好异地恋的女友来找我。有一天,我跟老板连招呼都没打,跟行政说了一声我不干了,收拾东西就走了。

手机关机,跟女友过了几天与世隔绝、幸福快乐、没心没肺的日子,我突然觉得该给公司一个交代,于是硬着头皮去公司,找老板谈谈。

恰巧,在公司电梯口见到老板,带着一群人,扛着大小设备,急匆匆出去外拍。老板见到我,愣了一下,指着我说:等我,回来再跟你说。

我吓坏了。这个老板平时脾气就大,这下还不得把我训死?

我在公司提心吊胆等了一个小时。我看着公司其他人忙碌喧哗,根本顾不上理我。难堪之极。

我找了张纸,写了一封长信,放在前台。算是交代了一下。

总之,我是落荒而逃。

这就是我职业生涯的开始。一个不光彩的、污点般的开始。

我想找那个年轻人,聊聊这件事。

我想告诉他,这件事成为我后来久久无法磨去的尴尬,心灵上的痒痕。

在那之后,我经常在洗澡的时候会突然想起自己落荒而逃的身影,内心奇痒无比,忍不住要狂嚎两嗓子才能疏解。

后来,我正式进入广告传播行业,在一家本土创意公司做了3年,后跟总监出来创业,到今年是第4年。

2012年的时候,机缘巧合,我又见到了当初那家影视公司的老板。

毕竟事过多年,我已经有了一颗平常心,能够跟人家主动打招呼了。他还记得我,很热情的跟我握手,问我近况,称赞我“有才华”,看上去一点也记不起来当初在电梯口的尴尬相遇。

我们一起吃了个饭,相约以后有机会合作。

此后,我们再也没有见过。

那次见面之后,我彻底原谅了自己。我也明白了一件事——几乎所有你认为尴尬的事,都只有你自己记得。别人早已忘却或不放在心上,只有你自己,当成久久无法消逝的“心头之痒”。

回望过去,我那个时候,很喜欢王小波。王小波有一篇文章,叫《工作与人生》。我当时读了没什么大的感受,比不上读《一只特立独行的猪》这么过瘾。
但现在回过头再看,这篇文章简直每一个字都写进了我的心里。

其中有三句,犹得我心:

**第一句是:“人从工作中可以得到乐趣,这是一种巨大的好处。”

第二句是:“总而言之,干什么都是好的;但要干出个样子来,这才是人的价值和尊严所在。”

第三句是:“人在工作时,不单要用到手、腿和腰,还要用脑子和自己的心胸。”**

不知不觉,我发现自己在面对工作时,态度与自己的人生偶像完全一致了。这让我感到振奋。
仿佛我经历了一次连自己都未察觉的修炼。如今已经印证,修为在身,境界如常。

而这种面对工作的态度和认知,是从什么时候开始的呢?就是从那段难堪的起点开始的,从那久久无法消散的心头之痒开始的。
那段难堪的经历,以及后来不断的自我反省,以及多年来全心投入工作的历练,使我重新认识了“工作”这件事。以及我应该如何对待“工作”。

是的。假如我有机会再见到那个年轻人,我会跟他谈谈以上这些。

原文: http://jianshu.io/p/6ff3d4113be6

引言

写程序的时候经常要处理命令行参数,本文描述在Bash下的命令行处理方式。

选项与参数:

如下一个命令行:

1
./test.sh -f config.conf -v --prefix=/home

我们称-f为选项,它需要一个参数,即config.conf, -v 也是一个选项,但它不需要参数。

–prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,/home可以直接写在–prefix后面,即–prefix/home,更多的限制后面具体会讲到。
在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。

  • 手工处理方式
  • getopts
  • getopt

下面我们依次讨论这三种处理方式。

手工处理方式

在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:

  • $0 : ./test.sh,即命令本身,相当于C/C++中的argv[0]
  • $1 : -f,第一个参数.
  • $2 : config.conf
  • $3, $4 … :类推。
  • $# 参数的个数,不包括命令本身,上例中$#为4.
  • $@ :参数本身的列表,也不包括命令本身,如上例为 -f config.conf -v –prefix=/home
  • $* :和$@相同,但”$“ 和 “$@”(加引号)并不同,”$“将所有的参数解释成一个字符串,而”$@”是一个参数数组。如下例所示:
1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash

for arg in "$*"
do
echo $arg
done

for arg in "$@"
do
echo $arg
done

执行./test.sh -f config.conf -n 10 会打印:

1
2
3
4
5
6
7
8
9
-f config.conf -n 10 #这是"$*"的输出

-f #以下为$@的输出

config.conf

-n

10

所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。如

./test.sh 10

而很少使用./test -n 10这种带选项的方式。 典型用法为:

1
2
3
4
5
6
7
8
9
#!/bin/bash

if [ x$1 != x ]
then
#...有参数
else
then
#...没有参数
fi

为什么要使用 x$1 != x 这种方式来比较呢?想像一下这种方式比较:

if [ -n $1 ] #$1 不为空

但如果用户不传参数的时候,$1为空,这时 就会变成 [ -n ] ,所以需要加一个辅助字符串来进行比较。

手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。

getopts/getopt

处理命令行参数是一个相似而又复杂的事情,为此,C提供了getopt/getopt_long等函数,
C++的boost提供了Options库,在shell中,处理此事的是getopts和getopt.

getopts和getopt功能相似但又不完全相同,其中getopt是独立的可执行文件,而getopts是由Bash内置的。

先来看看参数传递的典型用法:

  • ./test.sh -a -b -c : 短选项,各选项不需参数
  • ./test.sh -abc : 短选项,和上一种方法的效果一样,只是将所有的选项写在一起。
  • ./test.sh -a args -b -c :短选项,其中-a需要参数,而-b -c不需参数。
  • ./test.sh –a-long=args –b-long :长选项

我们先来看getopts,它不支持长选项。

使用getopts非常简单:
代码

#test.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash

while getopts "a:bc" arg #选项后面的冒号表示该选项需要参数
do
case $arg in
a)
echo "a's arg:$OPTARG" #参数存在$OPTARG中
;;
b)
echo "b"
;;
c)
echo "c"
;;
?) #当有不认识的选项的时候arg为?
echo "unkonw argument"
exit 1
;;
esac
done

现在就可以使用:
./test.sh -a arg -b -c

./test.sh -a arg -bc
来加载了。

应该说绝大多数脚本使用该函数就可以了,如果需要支持长选项以及可选参数,那么就需要使用getopt.
下面是getopt自带的一个例子:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#!/bin/bash

# A small example program for using the new getopt(1) program.
# This program will only work with bash(1)
# An similar program using the tcsh(1) script language can be found
# as parse.tcsh

# Example input and output (from the bash prompt):
# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
# Option a
# Option c, no argument
# Option c, argument `more'
# Option b, argument ` very long '
# Remaining arguments:
# --&gt; `par1'
# --&gt; `another arg'
# --&gt; `wow!*\?'

# Note that we use `"$@"' to let each command-line parameter expand to a
# separate word. The quotes around `$@' are essential!
# We need TEMP as the `eval set --' would nuke the return value of getopt.

#-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项
#如-carg 而不能是-c arg
#--long表示长选项
#"$@"在上面解释过
# -n:出错时的信息
# -- :举一个例子比较好理解:
#我们要创建一个名字为 "-f"的目录你会怎么办?
# mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用
# mkdir -- -f 这样-f就不会被作为选项。

TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
-n 'example.bash' -- "$@"`

if [ $? != 0 ] ; then echo "Terminating..." &gt;&amp;2 ; exit 1 ; fi

# Note the quotes around `$TEMP': they are essential!
#set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了
eval set -- "$TEMP"

#经过getopt的处理,下面处理具体选项。

while true ; do
case "$1" in
-a|--a-long) echo "Option a" ; shift ;;
-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;
-c|--c-long)
# c has an optional argument. As we are in quoted mode,
# an empty parameter will be generated if its optional
# argument is not found.
case "$2" in
"") echo "Option c, no argument"; shift 2 ;;
*) echo "Option c, argument \`$2'" ; shift 2 ;;
esac ;;
--) shift ; break ;;
*) echo "Internal error!" ; exit 1 ;;
esac
done
echo "Remaining arguments:"
for arg do
echo '--&gt; '"\`$arg'" ;
done

比如我们使用

./test -a -b arg arg1 -c

你可以看到,命令行中多了个arg1参数,在经过getopt和set之后,命令行会变为:
-a -b arg -c -- arg1
$1指向-a,$2指向-b,$3指向arg,$4指向-c,$5指向–,而多出的arg1则被放到了最后。

总结

一般小脚本手工处理也许就够了,getopts能处理绝大多数的情况,getopt较复杂,功能也更强大。
有问题请指出,不胜感激。

原文:http://www.cnblogs.com/FrankTan/archive/2010/03/01/1634516.html
参考资料:http://su1216.iteye.com/blog/1926382

结合静态站点托管服务Github Pages与博客生成工具Jekyll,搭建博客站点,有着部署成本低、易于维护的特点。诚然,Jekyll可以与Github Pages无缝集成,专业人士通过pull request就可以发布内容,但不易用是其最大的问题。Prose是一个基于Github PagesJekyll内容编辑器,它的出现使得内容编辑更快、更方便。

开通Github Pages服务

Github项目首页,点击进入后台管理页面

图1:Github项目管理后台入口[1]

点击”Automatic Page Generator”按钮生成站点服务

图2:Github项目页面生成器[1]

使用Markdown标记语言编辑站点内容,点击”Continue To Layouts”按钮

图3:Github项目页面预览[1]

预览并发布

图4:Github项目页面发布[1]

到这里,一个Github站点就生成了:http://{accountName}.github.com/{projectName}

使用Prose所见即所得的编辑特性

尝试Prose非常简单,首先通过Github账户身份验证,便可以导航到相应的站点

图5:Prose验证页面[2]

着陆页会依次列举个人代码库(Repository)

图6:Prose代码库列表[2]

选中之前开通Github Pages服务的代码库,可以浏览相应的文件以及创建新的文本文件

图7:Prose代码库内容列表[2]

编辑内容的时候,Prose支持Markdown标签的高亮显示

图8:Prose编辑器高亮特性[2]

任意时刻,都可以点击”Preview”按钮预览当前编辑的内容

图9:Prose编辑器预览特性[2]

Prose附加特性

在菜单工具条点击”M”按钮,可以获取Markdown标签参考语法列表

图10:Prose编辑器Markdown语法参考[2]

在菜单沟工具条点击”Metadata”按钮,可以看到文档的元数据以YAML的格式展现

图11:Prose编辑器元数据特性[2]

Prose项目的架构特点与展望

Prose的架构实现是以BackboneJekyll为基础,应用托管在Github上,浏览器端直接与GitHub API交互。鉴于浏览器端无法直接与Github通过OAuth交互,服务器后端处理用户身份的验证,具体的实现可参照Gatekeeper

感兴趣的读者朋友既可以选择Prose作为Github项目博客的内容编辑器,又可以参与Prose**项目的建设(Prose**完全基于BSD开源协议),搭建本地开发环境请参照http://prose.io/help/internals.html

引用

[1] https://help.github.com/articles/creating-pages-with-the-automatic-generator

[2] http://developmentseed.org/blog/2012/june/25/prose-a-content-editor-for-github/

原文: http://www.infoq.com/cn/news/2012/07/prose-github-content-editor

谢邀。

看了一下几个高票答案,讲的都是故事,都很感人,我就不催泪了,不过我需要对这些故事做一个理论补充——男人的温柔是不可能独立存在的。

So easy,如果一个男人拥有的只是温柔,体贴和任劳任怨,就像是你备胎中最听话的那一位一样。他会因为你的QQ签名改成了“下雨了,心情不好”而打20个电话给你只为给你讲个笑话;他会在你生理期的时候每天给你发短信叫你别着凉and多喝水;他会在你忙到不得不挂掉他电话之首写一封亲笔信来表达他对你的思念。

如果他只会这些,他不上进,也没有野心,更没有钱,也不会去思考如何赚钱,他有大把的时间,但是他却选择了花在游戏和牵挂你身上。作为女人,你还会喜欢他么?我相信大部分人的答案都是否定的。如果有人就是喜欢这一类男人,那我想说大学里面有很多,很多。

只有当男人有了足够的能力,社会地位或是财富之后,他的温柔具备杀伤力,我是男人,也是过来人,我知道一点:学习温柔是不需要成本的。换句话说,这玩意基本上不用学都会。一个大老粗也懂得应该对心爱的女人好一点,迁就一点,忍让一点。这在我们童年时期就已经被长辈教育过无数次了。他们总是告诉我们,男孩子要让着女孩子。

所以男人的温柔并不值钱。只有当这个男人足够强大之后,他的温柔才值钱。因为当一个男人飞黄腾达之后,他的心态会随之膨胀,他会目中无人,他会觉得他有钱有地位所以身边的人都应该围绕着他转。

很早之前的某一天,本来是要去外地看女朋友,但我犯懒了,那一刻我突然觉得我这么累的在工作,你作为我的女人怎么就不能多为我考虑一下,怎么就不能主动来看我?于是我找了一个理由说临时有工作上的事情去不了了,如果可以的话,不如你过来看我。结果她说,那下个月吧,你有工作就去。听到这句话的时候我生气了,狠狠的生气了。我觉得这女人真的太二,太不懂我。和她分手很久之后,我突然想明白了,二的是我,我已经被越来越高的社会地位冲昏了头脑,我没有做到一个男朋友的分内之事。更别提什么温柔了。我膨胀的太厉害,我失去了为他人思考的能力。我觉得这样下去要完蛋。也就是那时候我突然明白了清华的校训——厚德载物。

人都是这样,越强大越自傲。这是非常恐怖的,所以傲慢被定为七宗罪之首。同样的例子时时刻刻都在发生,就像是昨天在盐Club的前排会场里,我看到某个大V毫不留情的拒绝了一个粉丝的合影要求,甚至没有一句解释。甚是心寒。

相反的我看到有很多很强大也很温柔的男人例如马英九,李嘉诚,和《这个杀手不太冷》中的leon。无一不是拥有了强大的能力之后还能够保持一颗善良而谦和内心。我觉得这就是一个男人的温柔。

当然还有那些网络小说,女人的A片,有哪一个男主角不是家财万贯,武功高强,有勇有谋,帅的一逼?按照他们的人物设定基本可以坐拥天下,傲视众生甚至是扭曲时空。但无独有偶的他们哪一个在女主角面前不是谦谦君子,温润如玉的呢。如果这些男主角身上少了强大或是温柔中的任何一项,女人拿什么来高潮?

——————————

我不希望有些朋友带着偏见来看待这个问题,或是拿出现在的男朋友做比较。请不要说类似“不会呀,你看我现在的男朋友虽然没钱,但是他对我好呀”这样的话。那是因为你们在机缘巧合下走到了一起,你开始在这段感情和这个男人身上投资,无论是时间精力还是金钱,时间越长,你投资的就越多,也就越难以抽身。这就像是人们总是会试图维护自己的立场和想法一样,即使你知道那是不对的。

我更加不希望一些男性同胞误解我在嘲讽,也请不要自我矮化。那不是我的本意。我只是想说出事实,然后我们一起加油。

知乎原文:http://www.zhihu.com/question/23853217

初出茅庐的你带着仍残留墨香的毕业证书踏上工作岗位,马上就被书上没写的规则和各种繁杂的日常事务来了个下马威。这样的故事实在是司空见惯,编程工作也不例外。

没有几个学生能 100% 为自己的第一份真正的工作做好准备。如果你不想成为其中之一,请学学以下这 10 项无需手把手指导就能学会的基本技能:

1、版本控制系统(VCS)

VCS 也许是计算机课程最大的疏漏。这些课程光记得教如何写代码,但却往往忘记教学生如何去管理代码。每一个程序员都应该懂得利用 Git 或 Subversion 有效地创建 repository(仓库),编辑与提交代码,进行分支与合并,了解项目工作流。

2、学会写作

身为程序员要写的不只有代码。你还要写项目的发布说明,给版本控制写提交消息,在系统里面写漏洞报告。这些和许多地方都需要清晰有效的文字交流—但这个技能计算机科学却很少强调。

3、正则表达式

正则表达式本身就是一门语言,每一个现代程序员都要擅长。每一门现代语言都支持正则表达式或者有相关标准库。如果代码需要校验某字符串是否含有 5 个字符、1 个破折号和 1 个数字,你应该马上就能写出 /^[A-Z]{5}-\d$/。

4、库的使用

现在已经是 2014 年,所以没人需要用正则表达式从 URL 析取主机名了。因为每一门现代编程语言都有执行常用功能的标准库。

程序员需要明白,那些经过开发、测试和调试的代码通常要比自己重新写的代码更好。更重要的是,无需编写的代码实现起来要快得多。

5、SQL

很多人的 SQL 都是在工作中学会的。数据库怎么会是选修课呢?有不用数据库的吗?

把数据存进平面文件的时代已经结束了。一切东西都要进出数据库,而 SQL 则是存取数据的语言。这是一门说明性语言,不是程序语言,所以用它来解决问题时需要新的思考方式。每一个程序员都应该了解数据库标准化基础,能够执行 SELECT(及 INNER、OUTER JOIN)、INSERT、UPDATE 和 DELETE。

6、会用IDE、编辑器及CLI工具

只懂用锯子的木匠永远也无法出师,所以计算机专业毕业的人只懂 Notepad 或 pico 令人惊诧。编程工具帮助操纵代码及其他数据,令程序员生活变得容易。所以每一个程序员都应该知道命令行、shell 脚本、find、grep 及 sed 的使用。

7、调试

每一个程序员都应该知道利用交互式调试器或在代码中点缀一些输出语句来调试程序。通过逐步求精来跟踪问题的能力实在是太重要了。

8、防错性编程

错误总是难免的,哪怕是明星程序员也不例外。失控是世界的常态,出错毫不奇怪。防错性编程正是理解了这个事实。如果东西不会不出错,我们就不会检查文件打开成功与否,不会检查客户 ID 是否合法数字,不用测试代码是否允许正确。

程序员需要知道,编译器告警是有用的工具,可让我们生活得更舒适,而不是要避而远之的麻烦事。每一个程序员都应该知道为什么每一个 PHP 程序都要这样开头:

set_error_reporting(E_ALL)

每一个 Perl 程序都要写上这些语句:

use strict; use warnings;

9、团队协作

很少编程工作会让你自己一个人完成,如果你经常这么做,智力会受损,表现会变弱。你的代码必须与别人的交互或者混合。再有才的程序员,如果无法与别人协作,都会给项目造成负面影响,并迅速成为组织的负担。

10、利用现有代码

在学校的时候,每一次作业都是一个新项目。但现实世界不是这样的。对于刚工作的人来说,所接到的第一项任务往往是修改代码漏洞。然后,再在现有代码库的基础上为现有系统增加一个小功能。设计新代码那是几个月后的事情,如果幸运的话。

[本文编译自:blog.newrelic.com]

原文: http://www.36kr.com/p/212678.html?ref=related

mysql 的一般登陆方式是这样的

1
mysql -u $MYSQL_ROOT -p $MYSQL_PASS -h 192.168.10.1

但是,你有两个方式可以使用无密码提示的登陆,一个是修改/etc/my.cnf文件,一个是修改~/.my.conf 文件。

1
$ vi ~/.my.cnf
1
2
3
4
[client]
user=alice
password=alice_passwd
host=192.168.10.1

如果是修改my.cnf文件,把它加到文件末尾就行了。你可以直接使用

1
mysql -u root

登陆,不会再提示密码错误。但如果你仍然使用

1
mysql -u root -p

的方式,它还是会提示你输入密码的。

确保文件是只读的

1
$ chmod 0600 ~/.my.cnf

这样设置以后,你每次使用命令mysql就可以不要密码了,自动进入mysql中。

0%