Tag Archives: Raspberry Pi

发挥余热的Raspberry Pi 1

迁移到Raspberry Pi2之后,原来的Pi1继续发挥余热——接着个PS2 Eyetoy摄像头,每小时自动拍照、获取空气质量指数、发twitter。当然,Eyetoy拍出来的渣画质不能看,只是做着玩的。

这里记录一下实现的细节。

  • 拍照
    树莓派的官方镜像的kernel已经支持很多摄像头了,USB接口的Eyetoy插上去,直接就有/dev/video0设备。
    各种软件都可以拍照,比如说fswebcam, streamer,等等。我用的是fswebcam

      fswebcam -r 640x480 -S 20 --title "xxx"
    

    其中`-r`是分辨率,不多说了;`-S 20`是跳过20帧,因为如果只取第一帧,画面会不完整,曝光也不对,20帧(大概3秒之后)差不多就够了; `–title “xxx”`是嵌在图像里的标题。

  • 获取AQI
    在aqicn.org上查了一下,离家最近的是张江的监测点,网页是http://aqicn.org/city/shanghai/pudongzhangjiang/
    网页内容里已经带了AQI指数,所以要获取AQI的数值,直接在页面里用正则表达式匹配一下就行了。

        pattern = (' Air Pollution measured on (\w+) (.+): ' +
                   city.capitalize() +
                   ' overall air quality index is (\d+)')
        results = re.findall(pattern, content)
    

    得到的`results[0]`就是匹配到的内容,是个tuple,分别是weekday,time,AQI。

  • 发Twitter
    网上有各种twitter的库,google一下,选了个简单的twython。
    使用 Twitter API 也超简单,到https://apps.twitter.com/申请一个app拿到consumer key/secret;
    再generate一个access token/secret;
    然后用这4个参数初始化twython,发带图片的tweet调用`update_status_with_media`,搞定。
    不过`update_status_with_media`已经过时了,以后应该需要用`upload_media`+`update_status`来搞定,不过现在还能用,先这么用着。

      CONSUMER_KEY = 'YOUR-CONSUMER-KEY'
      CONSUMER_SECRET = 'YOUR-CONSUMER-SECRET'
      ACCESS_KEY = 'YOUR-ACCESS-KEY'
      ACCESS_SECRET = 'YOUR-ACCESS-SECRET'
      ...
      api = Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET)
      image = open(imagefile, 'rb')
      api.update_status_with_media(media=image, status=tweet)
    
  • 其它
    要定时跑脚本,crontab里加一个每小时跑一次的脚本就行;
    要翻墙,用的是shadowsocks + cow,然后在脚本前加上http/https proxy的环境变量:

    0 * * * * http_proxy=http://127.0.0.1:7777/ https_proxy=http://127.0.0.1:7777/ /home/pi/pi-pudongair/main.py
    

完整的code放在了gist上:https://gist.github.com/mine260309/771512fc912d283496d9

效果见 @PiPudongAir,欢迎关注。

Share

RaspberryPi2克隆Pi1的系统

RaspberryPi 2发布了有一段时间了,RS版本一直没货,忍不住在淘宝上买了个国产的版本。

到手之后,发现果然可以直接用Pi1的系统:

  • 如果原来就是用TF转SD卡的,直接插到Pi2上就可以启动了
  • 如果原来用的是SD卡,最简单的方式是把SD卡的内容dd出来,然后dd到TF卡上
  • 如果像我一样发现同样都是16G的卡,SD卡的block数多于TF卡,dd的时候size不对,很可能会有问题,只能按下面的方式来clone系统了。

以下步骤假设Pi1的系统在SD卡上,要把这个系统clone到一张略小于SD卡的TF卡上:

  1. 给TF卡分好区,最简单(但是有点花时间)的方式就是直接dd官方的镜像,比如说
      dd bs=4M if=2015-02-16-raspbian-wheezy.img of=/dev/<your-device>
    

    然后启动系统,在raspi-config的菜单里Expand Filesystem,这样TF卡的分区就弄好了。

  2. 备份SD卡的内容,假设我备份到~/raspberry_pi/
      sudo tar czvf ~/raspberry_pi/pi1_boot.tar.gz --directory <path-to-boot> . #备份boot分区
      sudo tar czvf ~/raspberry_pi/pi1_rfs.tar.gz --directory <path-to-rootdisk> . #备份rootfs
    
  3. 删除TF卡各分区的内容
      sudo rm -rf <path-to-boot>/*
      sudo rm -rf <path-to-rootdisk>/*
    
  4. 把tar包解压到TF卡上
      sudo tar xzvf ~/raspberry_pi/pi1_boot.tar.gz -C <path-to-boot>
      sudo tar xzvf ~/raspberry_pi/pi1_rfs.tar.gz -C <path-to-rootdisk>
    
  5. 把TF卡插到Pi2上,启动,应该一切正常!
Share

自家网络的连接与设备

以前介绍过在一根网线上承载两路网络,用了近两年,感觉不错。现在家里的网络设备越来越多,所以分享一下我家的网络连接和设备情况。

先上图
家庭网络设备

稍微详细的介绍:

  • 电信的光猫,4个LAN口中其中一个是IPTV的VLAN,其余的3个可以当LAN来使用;
    用admin帐户登录,删除自带的PPPoE拨号,因为我要用自己的路由器拨号(注意记住原来的VLAN ID)
  • 路由器是Netgear的WNDR3700,UpLink接光猫的LAN口来PPPoE拨号;
    DHCP为PC、RaspberryPi、Laptop设置静态IP,设置DMZ主机为RaspberryPi;
    自带DDNS功能,不过Dyndns的免费服务没了,没用。。。
  • 树莓派用来24*7不间断工作(当然,时不时重启时例外^_^),上面装的主要服务有:
    WorkdPress (nginx + php + mysql)
    Samba Server
    DDNS(dyn.dns.he.net)
    接个老式硬盘当NAS(注意最好格式化成ext4,比NTFS快多了)
    Crontab里用几个脚本把Wordpress和一些重要文件备份到PC
    同时把PC上的Download文件夹rsync到老硬盘上
  • 台式机一般只有晚上才开,所以crontab是晚上备份,备份到Dropbox的文件夹,所以自动同步到Dropbox上;
    下载的电影、美剧都放在Download文件夹里,以便让RPi同步到老硬盘上,这样就算PC关机,一样能看;
    当然,更多的时候是开着PS3 Media Server当DMS,然后在PS3上看高清电影~
    不过台式机放在小房间,没铺网线,只能用电力线适配器来接,网速大概只能到90M左右,有待改善(如果有好建议,一定告诉我!)
  • PS3,不用说,高清的游戏机+播放器,画质、音效最佳;
    客厅的电视机还接着一个山寨的机顶盒,能看Samba上的内容。
  • 在卧室里放一个OTT的机顶盒(比如说小米盒子),既可以看在线的,也可以看PC和RPi上的内容。
    当然,还有AirPlay和Miracast的功能,偶尔会用,也挺不错的。

其它手机、Pad、笔记本,都是wifi连接,做该做的事情,就不多说了。

总之,因为路由器和树莓派是不关机的,而且树莓派的硬盘上的内容基本上和PC是同步的,所以我觉得这样最大的好处是:

  1. 免费的(喂,电费呢!)个人博客,以及Dropbox的备份
  2. 无论何时(不管PC是不是开着),都能在pad或者电视上看片~

Q.E.D.

Share

Nginx https load-balance on Raspberry Pi

我的Raspberry Pi工作了大约半年之后,文件系统开始出现莫名其妙的问题,各种文件都出现乱码,以至于某系统命令一执行就segment fault。到重新“安装”系统的时候了。

之前主要跑的服务是我的博客,nginx + wordpress搭的,在RPi上因为CPU的问题(php-fpm执行时几乎占满cpu),响应比较慢。既然重新弄了,考虑把某些请求交给家里的其它机器来处理。
家里还有一台跑Ubuntu的笔记本,希望满足如下要求:
1) 如果笔记本开机着,http请求(几乎)都交给笔记本处理;
2) 如果笔记本关机,http请求都由RPi来处理;
这些应该是完全自动实现的。

在Stackoverflow上问了这个问题,有人提示说可以通过nginx的load-balance功能来实现我的需求。于是开始google一番,找到了解决方案。
基本的思想是,把nginx配置成反向代理,笔记本和RPi都作为upstream来处理http请求;通过nfs共享同一个wordpress目录;配置mysql让wordpress访问同一个数据库。
一步一步来配置这些。
其中Raspberry Pi的地址固定为192.168.1.100,笔记本的地址固定为192.168.1.101,数据库名为minewpdb,数据库用户名为minedb

1. 配置Mysql
mysql仍然放在RPi上,让mysql接受网络的请求,这样不同的机器可以用同一个mysql数据库。

sudo vim /etc/mysql/my.cnf
==> 把 bind-address 改成RPi的ip地址
bind-address            = 192.168.1.100

mysql -u root -p #登录mysql控制台
mysql> grant all on minewpdb.* to 'mineblog'@'192.168.1.100' identified by 'xxx'; # 本地RPi的wordpress访问
mysql> grant all on minewpdb.* to 'mineblog'@'192.168.1.101' identified by 'xxx'; # 笔记本的wordpress访问
mysql> quit;
sudo service mysql restart # 重启mysql服务

# 在RPi和笔记本上分别测试一下
mysql -u mineblog -h 192.168.1.100 -p # 如果能登录成功,就ok了

2. 配置wordpress
Wordpress仍然在RPi上,只要修改wordpress的config文件,把数据库的host,用户名和密码都设对就行了。

sudo vim /path/to/wordpress/wp-config.php
==> 修改DB_HOST等参数
define('DB_NAME', 'minewpdb');
define('DB_USER', 'mineblog');
define('DB_PASSWORD', 'xxx');
define('DB_HOST', '192.168.1.100');

3. 配置nfs
在RPi上设置nfs export,让笔记本mount它,这样可以保证跑的wordpress是同一份。


sudo vim /etc/exports
==> 添加wordpress目录到exports
/path/to/wordpress 192.168.1.101(rw,no_root_squash,insecure,sync,no_subtree_check)
sudo service rpcbind start  # RPi的nfs依赖于rpcbind
sudo update-rc.d rpcbind enable  # 设置rpcbind自动启动
sudo service nfs-kernel-server start  # 重启nfs

在笔记本上,mount这个目录:

sudo mount -t nfs 192.168.1.100:/path/to/wordpress /path/to/wordpress

4. 配置nginx
在RPi上要把nginx配置成反向代理,upstream是RPi和笔记本,端口号都是8000,真正的wordpress运行在8000端口上。
添加新的配置文件 /etc/nginx/sites-available/wordpress-load-balance,注意我把http的访问全部重定向到https,以防GFW

# Upstream to abstract backend connection(s) for php
upstream php {
server unix:/var/run/php5-fpm.sock;
}

upstream mineservers {
# 设置两个upstream, 其中笔记本优先,同时设置5s的fail_timout
# 因为局域网很稳定,所以max_fails设成1就行了,
# 如果fail就说明笔记本关机中,让RPi自己来处理
server 192.168.1.101:8000   weight=999 fail_timeout=5s max_fails=1;
server 192.168.1.100:8000;
}

server {
listen 80;
server_name mine260309.me;
rewrite     ^ https://$server_name$request_uri? permanent;
}

server {
listen          443 ssl;
server_name     mine260309.me;

ssl_certificate     /path/to/cert/mine260309.me.2014.chain.crt;
ssl_certificate_key /path/to/cert/mine260309.me.2014.key;
ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers         HIGH:!aNULL:!MD5;
access_log         /path/to/wordpress/logs/proxy.log;
error_log            /path/to/wordpress/logs/proxy_error.log;

location / {
# 代理到upstream
proxy_pass  http://mineservers;

### force timeouts if one of backend is died ##
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;

### Set headers ####
proxy_set_header        Accept-Encoding   "";
proxy_set_header        Host            $host;
proxy_set_header        X-Real-IP       $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

### Most PHP, Python, Rails, Java App can use this header ###
#proxy_set_header X-Forwarded-Proto https;##
#This is better##
proxy_set_header        X-Forwarded-Proto $scheme;
add_header              Front-End-Https   on;

### By default we don't want to redirect it ####
proxy_redirect     off;
}
}

server {
root /path/to/wordpress;
# 在8000端口监听
listen          8000;
server_name     mine260309.me;
... # normal wordpress configurations
}

在笔记本上用同样的配置就可以了。

这样,任何一个请求到RPi,它会让nginx优先反向代理到笔记本的nginx的8000端口,由笔记本来处理;
如果笔记本关机,在5秒钟之后它会fail,于是再由RPi自己的8000端口处理。

Q.E.D.

Share

迁移博客到Raspberry Pi上

之前博客host在amazon的服务器上,每个月15~16刀的支出着实不小。

现在有了Raspberry Pi了,基本上24小时开机,可以当一个小server用,所以想着把博客迁移到Pi上,反正访问量不大,肯定能承受得住。

Apache有点大,想想还是用nginx来跑wordpress吧。google一下,找到这篇文章:http://www.cnx-software.com/2012/08/03/wordpress-for-raspberry-pi-using-nginx-and-mysql/
基本上把在Pi上安装http server和部署wordpress的要点写清楚了。

不过我要的不是一个新的wordpress,而是迁移原来的博客,所以也在这里记录一下。因为是事后记录,可能有遗漏或者错误,仅供参考。

1. 安装nginx, php,mysql等

sudo apt-get update
sudo apt-get install nginx php5-fpm php5-cli php5-curl php5-gd php5-mcrypt php5-mysql php5-cgi mysql-server

2. 参考上面的link,把nginx和php的配置文件配好,因为我还要用https(防GFW),所以相比那篇文章里的配置,多了ssl的配置

# Upstream to abstract backend connection(s) for php
upstream php {
server unix:/var/run/php5-fpm.sock;
}
server {
## Your only path reference.
root /srv/www/wordpress;
listen          80;
listen          443 default_server ssl;
## Your website name goes here. Change to domain.ltd in VPS
server_name     mine260309.me;

ssl_certificate     /home/pi/cacert/mine260309.me.StartCom.cert;
ssl_certificate_key /home/pi/cacert/mine260309.me.key.pem;
ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers         HIGH:!aNULL:!MD5;
access_log      /srv/www/wordpress/logs/access.log;
error_log       /srv/www/wordpress/logs/error.log;

## This should be in your http block and if it is, it's not needed here.
index index.php;

location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location / {
# This is cool because no php is touched for static content
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_pass php;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
}

记得创建对应的文件夹,否则nginx会访问失败:

sudo mkdir -p /srv/www/wordpress/
sudo mkdir -p /srv/www/wordpress/logs

3. 把备份的文件拷过来,恢复wordpress文件夹和数据库。

3.1 我的备份是这样的一个脚本,crontab每周跑一次,备份过的文件会自动被dropbox同步。(注意用户名和密码是自己设的mysql的用户名、密码)

#!/bin/sh
# Back my web with clear password!
mysqldump --add-drop-table -h localhost -u  --password= minewpdb | bzip2 -c > ~/Dropbox/MyWebs/blog.bak.sql.bz2
tar -czf ~/Dropbox/MyWebs/blog.bak.html.tar.gz /var/www/html

3.2 恢复的过程是:
a) 恢复mysql数据库

$ mysql -u root -p
mysql> CREATE DATABASE minewpdb;  #创建database,注意名字和之前用的一样
mysql> GRANT ALL ON minewpdb.* TO @localhost IDENTIFIED BY '';  # 创建一个myssql用户,方便起见,也和以前一样好了
$ mysql -u ec2-user -p minewpdb < /media/ent/blog.bak.sql # 恢复数据库

b) 恢复html文件夹,这个很简单,就是把blog.bak.html.tar.gz解压出来,放到/srv/www/wordpress目录就行了
然后就可以先在本地测试了,确认wordpress没有问题之后,就是域名了。

4. 域名DDNS

这一块还没玩过,只能做尝试了。

先测试了url forwarding,在dyndns.org有个免费域名mine260309.dyndns-at-home.com,这个是可以DDNS的,然后在GoDaddy里设置了forwarding,然而无论是设置成http://的还是https://的,ssl都有问题(我的博客用了WordPress HTTPS),上推去问,@wzyboy同学说可以用he.net的服务,去google了一下,果然是个好东西。参考http://www.bidon.ca/en/random/2011-06-16-using-dynamic-dns-feature-dnshenet

4.1 上dns.he.net,注册后,可以免费设置50个域名。
1) 添加mine260309.me;
2) Edit Zone -> New A -> Enable entry for dynamic dns
3) 点击”refresh”图标 -> Generate Key,记住这个key,以后给ddclient用
4.2 然后在pi上下载ddclient

apt-get install ddclient

#安装的过程中会有preconfig:

remote server: dyn.dns.he.net
username: mine260309.me
password:
domain: mine260309.me

service ddclient status

确认ddclient工作正常。

4.3 在GoDaddy的设置里把Forwarding关掉,然后手动设置Nameserver为ns1.he.net, ns2.he.net, …

最后测试,一切正常!

不过因为在墙内了,发完博客自动发推的功能木有了,当然这个可以用别的服务搞定就是了,以后再说~

Share