sftp用户创建与设置

环境:ubuntu server 14.04
目的:用户只能通过 sftp 访问指定目录,并且不能登录 shell

网上有很多这方面的介绍,最有价值的是这里。但是按照这篇文档还是遇到了两个坑:

  1. 配置没有加载
  2. sshd 无法正常启动

这并不能说是参考文章,只是它没有提到而已。解决方法在下面会以斜体的字体表明。

下面是需要的步骤;

创建用户组
1
sudo addgroup sftponly

之后将通过用户组来控制权限,所以创建一个新的用户组是有必要的。

创建用户
1
sudo useradd -d /home/bob -s /usr/lib/sftp-server -M -N -g sftponly bob

把新用户 bob 加入到 sftponly 这个用户组。

1
sudo passwd bob

为新用户 bob 设置密码。

1
echo "/usr/lib/sftp-server" >> /etc/shells

把 sftp-server 作为一个 shell 加入到 shell 列表。

创建用户目录
1
sudo mkdir -p /home/bob/uploads
sudo chown bob:sftponly /home/bob/uploads

为新用户创建 home 目录和 sftp 目录,并设置所有权。

修改配置
1
sudo vim /etc/ssh/sshd_config

打开 sshd_config 配置文件,把 Subsystem sftp /usr/lib/openssh/sftp-server 注释掉,在下面加上 Subsystem sftp internal-sftp

最后一行添加上:

1
Match group sftponly
    ChrootDirectory %h
    X11Forwarding no
    AllowTcpForwarding no
    ForceCommand internal-sftp

注意:上面的代码一定要加在最有一行,否则 sshd 会无法启动

重启 sshd
1
sudo service ssh restart

注意:参考中使用sudo /etc/init.d/ssh restart来重启 sshd,没有任何的效果。

当使用 service 来重新启动的时候,如果正常会显示:

1
ssh stop/waiting
ssh start/running, process 12760

如果出错,则只会显示

1
ssh stop/waiting
ssh start/running

`

docker之程序员系列 (一)

因为我主要使用 ubuntu 做服务器,所以以下的操作都是在 ubuntu server 14.04下进行。

OSX 下的选择

虽然官方提供了一个工具(boot2docker),但是说到底,它其实也是在 OSX 下使用 virtualbox 虚拟了一个 linux 出来,然后再在 linux 下进行 docker 操作。那么对于我这样的凡事都希望清晰、简单的人来说,第一选择肯定不会使用这个工具,而是会选择从头开始。如果你和我一样,那么我们需要下面这几样东西:

  1. virtualbox
  2. ubuntu server 14.04

linux 安装完成之后,为了更好的使用,你需要知道几件关于 virtualbox 的事情:

  1. 如何映射端口
  2. 在命令行启动虚拟机

映射端口在 virtualbox 的gui 界面中就可以简单的完成。下面我贴出命令行启动和保存虚拟机的代码:

1
VBoxManage startvm Ubuntu --type headless
1
VBoxManage controlvm Ubuntu savestate

Ubuntu 下 docker 安装和配置

docker 安装和配置和其他程序没有什么两样。使用apt-get进行安装:

1
2
sudo apt-get udpate
sudo apt-get install docker.io

此时 docker 的每次运行都需要加上前缀sudo,比较麻烦。可以进行如下的处理:

1
2
sudo groupadd docker
sudo gpasswd -a ${USER} docker

其中,USER替换成 ubuntu 的当前用户。具体可以参考 askubuntu.com

第一个 image

现在我们需要一个 image。这里也有几种选择:

  1. 从网上下载。如果网络速度比较快的话,可以使用下面的命令从 docker 官方库中搜索并拉一个 image 下来:

    1
    2
    docker search ubuntu
    docker pull ubuntu
  2. 自己做一个

如果你选择自己做一个,也是有多个选择,但这里我选择简单一点,使用 debootstrap 工具。而使用这个工具,不需要一个参数一个参数自己输入,docker 官方提供了一个脚本mkimage.sh

1
2
3
git clone https://github.com/docker/docker.git
cd docker
./mkimage.sh

按照提示进行即可。

运行容器

现在我们有了一个baseimage,在我们启动它之前,我们可以给它打一个 tag。

1
2
3
4
# 查看当前用于的 image
docker images
# 给 image 打 tag,格式为[repository[:tag]]
docker tag <image_id> ubuntu:14.04

当我们拥有多个 image 之后,可以很容易的通过 tag 来识别各自的用处。

1
2
# 运行这个 dock
docker run -it --name first ubuntu:14.04

这样就启动了一个容器,把这个容器命名为 first,并且获得一个控制台。

保存修改

容器的一大优势就是很方便的丢弃一些数据和状态。如果你只是临时性的运行一下程序,验证一些想法,容器是非常方便的。当退出并且删除容器之后,所有的数据都会被抛弃。
但是当你需要保存数据或是状态,那么需要显示的进行保存。docker 的一些概念和 git 相似,这里也是通过 commit 来保存容器:

1
docker commit first tag

tag可以是原来的 image 的 tag,也可以是一个新的 tag。

blog 从 Dreamhost 搬到了 Linode

Dreamhost 从国内访问越来越差,速度慢不说,有时候还连不上。

除此之外,每月$8.5的共享服务器在价格方面也完全没有优势,没有 root 权限,很多东西都无法操作。

而且,虽然他们说硬盘大小是没有限制的,但是上次放了多一点东西就发邮件过来要求删除,说什么不能作为备份用途云云。

早有打算换一个服务商,只是一直没有找到合适的。这次买了 Linode 的 vps就把 blog 和 web 以及 git 都搬了过来。blog 也从 wordpress 换成了 hexo。因为 vps 上有足够的权限,分别做了 php 和 nginx 两个 docker 来支持这些服务。

Dreamhost 上现在只留下了域名服务,以后发现有更优惠的域名服务商之后再迁移出来。

Pomelo开发环境搭建之 Docker

因为不想把当前的 osx 的环境弄得更复杂以及想实战一下docker,所以选择了在docker下搭建pomelo 的开发环境,大致的过程如下:

一. 安装

  1. 安装 VirtualBox
  2. 在 VirtualBox 安装 Ubuntu server
  3. 在 Ubuntu 下安装 docker
  4. 在 docker 下下载 Ubuntu image
  5. 运行 Ubuntu image,下载各种工具
  6. 根据文档安装 pomelo

二. 配置

  1. 在 VirtualBox 中映射 Ubuntu 到 OSX 的 ssh 端口
  2. 在 VirtualBox 中映射 Ubuntu 到 OSX 的 pomelo 需要的端口
  3. 在 docker 下映射 Ubuntu container 到 Ubuntu host 的 pomelo 需要的端口

三. 文件

  1. 在 VirtualBox 中设置 OSX 到 Ubuntu 的共享文件夹
  2. 在 docker 下把 Ubuntu host 中的共享文件夹映射到 Ubuntu container

四. 调试

  1. 安装node-inspector,并指定web-port和 debug-port
  2. 编辑 pomelo 的工程中的 servers.json,为需要调试的服务器指定调试端口
  3. 在 Chrome 中按照node-inspector 的提示打开调试的 url

五. 问题

  1. 安装 pomelo 的时候花了很多时间,有些包比如 heapdump 总是出错,后来发现是没有安装 make 和 g++等开发工具
  2. 在 container 中用命令创建 pomelo 工程后在 OSX 下无法保存,发现是因为权限的问题。一个方法是在 container 中把目录和文件都改成 other 可写,另一个方法是在 OSX 下把 container 中创建的工程复制一份,把原来的工程目录删除即可
  3. 服务器指定调试端口(3005)后一直没有办法连上,Chrome 中也看不到工程的文件,此时换一个调试端口即可
  4. 在 container 中需要运行 node-inspector、server、client 以及其他的命令,但是只有一个控制台,解决的办法一个是把命令运行到后台,另一个安装 tmux

Quick-cocos2d-x 接入 protobuf

  1. 下载云风的 pbc:

    git clone git@github.com:cloudwu/pbc.git
    

    `
    把 pbc 下 src 目录复制到 quick 的 lua_extensions 目录下,并重命名为 pbc。

  2. 下载 lpeg,并同样复制到 lua_extensions 下
  3. 下载 struct,并同样复制到 lua_extensions 下
  4. 编辑 lua_extensions\lua_extensions[_more].c 文件,添加:

    `// protobuf

    include “pbc/pbc-lua.h”

    // lpeg

    include “lpeg/lptree.h”

    // struct

    include “struct/struct.h”

    … … static luaL_Reg luax_exts[] = {
    … …
    {"lpeg", luaopen_lpeg},
    {"struct", luaopen_struct},
    {"protobuf.c", luaopen_protobuf_c},
    
    … …

  5. 把 pbc,lpeg,struct 目录加入到 xcode 的工程中。比如游戏工程或是 quick-player 的工程
  6. 编译项目。

使用 Cocostudio 创建 listview item

为了快速开发一个小游戏,使用了 Cocostudio 2.0 作为 UI 编辑器。其实 Cocostudio 的功能比较弱,特别是针对稍微复杂一点的控件(Widget),无法做到所见即所得,不得不写一些代码。

游戏中用到了一个 listview,但是 Cocostudio2.0中没有 listview,所以只能写代码实现,这个是没有办法的。好在一个 listview 本身还是比较简单的,但是 listview 中的 item 可以很复杂,是否有办法简化呢?

尝试了很久之后,还真找到了一个迂回的方法,即:

  • 在 Cocostudio 中创建一个新的 Layer
  • 在 Layer 上编辑所需要的 item

这本来是一件比较简单的事情,但是问题在于 listview 的 item 只能是 widget,而 Cocostudio 2.0中 widget 有限,所以,尽量用 button 拼凑吧!

放出 listview 和 listitem 的 lua 代码:

local LISTVIEW_WIDTH = 340
local LISTVIEW_HEIGHT = 405
local listView = ccui.ListView:create()
-- set list view ex direction
listView:setDirection(ccui.ScrollViewDir.vertical)
listView:setBounceEnabled(true)
-- listView:setBackGroundImage("hall/di.png")
-- listView:setBackGroundImageScale9Enabled(true)
listView:setContentSize(cc.size(LISTVIEW_WIDTH, LISTVIEW_HEIGHT))
listView:setAnchorPoint(cc.p(0, 0))
listView:setPosition(cc.p(10, 12))
listView:addEventListener(listViewEvent)
-- SCISSOR
listView:setClippingType(1)
parent:addChild(listView)

local function createDefaultListItem()
local leaderboardItemLayer = cc.CSLoader:createNode("hall/LeaderboardItem.csb")
-- retrieve the widget. MUST be a widget
local listItemRoot = leaderboardItemLayer:getChildByTag(2001)
listItemRoot:removeFromParent()

local listItemRootSize = listItemRoot:getContentSize()
listItemRoot:setPosition(cc.p(LISTVIEW_WIDTH / 2.0, listItemRootSize.height / 2.0))

local default_item = ccui.Layout:create()
default_item:setTouchEnabled(true)
default_item:setContentSize(listItemRootSize)
default_item:addChild(listItemRoot)

return default_item
end

local default_item = createDefaultListItem()
listView:setItemModel(default_item)

for i = 1, 100 do
listView:pushBackDefaultItem()
end

-- set all items layout gravity
listView:setGravity(ccui.ListViewGravity.centerVertical)

--set items margin
listView:setItemsMargin(2.0)

常用正则表达式符号

转意符号

pattern meaning
\ % 改变下一个字符的属性,让普通字符包含特殊含义或者相反

字符匹配模式

pattern meaning
. 匹配除「\n」之外的任何单个字符。
x\ y 匹配x或y
[xyz] 匹配所包含的任意一个字符
[^xyz] 匹配未列出的任意字符
[a-z] 字符范围。匹配指定范围内的任意字符。
[^a-z] 匹配任何不在指定范围内的任意字符
….. 其他特殊的 patterns

数量限定

pattern meaning
* 匹配前面的子表达式零次或多次
+ 匹配前面的子表达式一次或多次。
? 匹配前面的子表达式零次或一次。
{n} 匹配确定的n次。
{n,} 至少匹配n次
{n,m} 最少匹配n次且最多匹配m次

贪婪模式取消

pattern meaning
? 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的

控制字符

pattern meaning
^ 匹配输入字符串的开始位置
$ 匹配输入字符串的结束位置

分组模式

pattern meaning
(xyz) 分组
\n 对分组的引用

tolua++:namespace导致的问题

在用cocos2d-x的时候,我们把自己的类和cocos2d-x的类混在一起,而是导出了一个独立的cpp文件。但是在pkg文件中没有注意处理cocos2d的namespace,导致了在lua脚本中,自定义类中获得的比如CCNode之类的对象无法访问成员函数。因为在cocos2d-x的pkg中,它是删除了namespace的,所以tolua++生成的代码是这样的:

 tolua_usertype(tolua_S,”CCNode”);

而在我的pkg文件中,由于没有处理namespace,生成的代码如下:

 tolua_usertype(tolua_S,”cocos::CCNode”);

这就导致了同一个类在lua脚本中被认为是两个不同的对象。

解决的方法很简单,去掉namespace即可。

指针vector初始化

C++中,在申明的时候初始化一个vector的时候可以指明vector的大小和默认值。但是如果用NULL来初始化指针的时候,会遇到问题。

class A;
vector<A > vtTest<2, NULL>;

在XCode中报错:说不能把int型赋值给A。原因就是NULL本身是不带具体的类型的,默认会被认为是一个int类型。

所以,解决的方法就是类型强制转换。