Archiva安装笔记

Apache Archiva是个开源的Artifact Repository。 网上关于Archiva的文档并不太多,因此我在安装过程中遇到一些麻烦。在此记录下解决问题的过程。

(Read More)

改善tmux的绑定

做前端开发通常需要打开好几个终端,运行vim编辑器、gulp watch或webpack,有时还要自己跑后台服务。 如果经常需要在修改代码之后切换到另一个窗口查看服务器端日志或者watch的编译情况, 就免不了多次使用tmux的绑定键(默认是Ctrl-B),麻烦且不说,时间长了小指也会很痛。

我找到了两个办法来解决这个问题。首先,利用tmuxinator按照给定的布局打开多个pane, 这样所需的信息能在同一个屏幕内看见,就不需要频繁切换窗口了。

安装tmuxinator之后执行tmuxinator new <project>就可以新建一个配置文件。 我的配置文件如下:

name: helloworld

# 设置项目根目录
root: ~/projects/helloworld

# 打开新窗口或pane之后首先激活virtualenv
pre_window: source .env/bin/activate


windows:
  - editor:
      # 设置pane的布局
      layout: 52dd,272x65,0,0[272x58,0,0,0,272x6,0,59{90x6,0,59,3,90x6,91,59,4,90x6,182,59,5}]
      panes:
        - vi
        - backend:
          - ./manage.py runserver 0.0.0.0:8000
        - frontend:
          - gulp watch
        - test:
          - npm test
  - extra:

上面我在同一个窗口内打开了4个pane,最大的第一个pane运行vi,其他三个小的pane分别运行前端和后端的命令。 另外还开了一个名为extra的窗口备用。

至于layout的值,可以先开启tmux打开所需数量的pane,然后用鼠标调整pane的大小至合适位置(需要在.tmux.conf里设置set-option -g mouse-select-pane on set-option -g mouse-resize-pane on), 最后执行list-window命令即可得到layout的参数。

另外要注意,如果.tmux.conf里设置了set -g base-index 1,那么同时也要设置set-window-option -g pane-base-index 1,否则tmuxinator会出错。

第二个方法是把窗口切换绑定到Alt/Option键,并且不设置前缀,这样只需按Option-1, Option-2就能切换多个窗口了。

bind -n M-1 select-window -t :1
bind -n M-2 select-window -t :2
bind -n M-3 select-window -t :3
bind -n M-4 select-window -t :4
bind -n M-5 select-window -t :5
bind -n M-6 select-window -t :6
bind -n M-7 select-window -t :7
bind -n M-8 select-window -t :8
bind -n M-9 select-window -t :9

如在iTerm2下使用,需要进入Preferences > Profile > Default > Keys中,将”Left option key acts as:”设置为”+Esc”,上述绑定才能正常工作。

(Read More)

[react]展示组件和容器组件

本文译自Presentational and Container Components

我发现在写React应用时,有个设计模式非常有用。如果你有React的经验,估计你已经知道了——它就是容器组件这篇文章讲得很清楚了,但我想再补充几点。

有个办法能让组件更易懂、更容易复用,那就是将组件分成两类。我称之为容器组件展示组件,但也有人叫胖组件和瘦组件(Fat and Skinny)、智能组件和非智能组件(Smart and Dumb)、状态组件和纯组件(Stateful and Pure)、画面和组件(Screen and Component)等等。尽管它们并不完全相同,但基本的理念是一致的。

我所说的展示组件如下:

  • 关心组件的外观
  • 内部可能包含展示组件和容器组件,并且通常有自己的DOM标签和自己的样式。
  • 通常可以用this.props.children包含其他组件。
  • 不依赖于app的其他部分,如Flux action或store等。
  • 不需要指定如何加载或操作数据。
  • 通过props明确地接收数据、发起回调。
  • 绝大部分情况下自己没有状态(即使有,也通常是UI状态,而不是数据)
  • 可以写成函数型组件,除非需要状态、生命周期钩子函数,或者需要性能优化等
  • 例如:PageSidebarStoryUserInfoList

容器组件如下:

  • 关心组件如何工作
  • 可以包含展示组件和容器组件,但一般不会有自己的DOM标签(除了一些wrapping div之外),绝对不会有样式
  • 为展示组件或其他容器组件提供数据
  • 调用Flux action并将其作为回调函数提供给展示组件
  • 通常是有状态的(stateful),因为通常被作为数据源使用
  • 通常不是手写,而是由高阶组件生成,如React Redux的connect(),Relay的createContainer(),Flux Utils的Container.create()
  • 例如:UserPageFollowersSidebarStoryContainerFollowedUserList

为清晰期间,我会把它们放在不同的目录下。

(Read More)

[react]关于容器组件

本文译自Container Components

React的许多设计模式都给我的代码带来了深远的影响,而容器组件模式就是其中之一。

在React.js大会上,Jason Bonta介绍了他们在Facebook是如何构建高性能组件的,其中包含了这段关于容器组件的精髓.

其思想很简单:

容器负责获取数据,然后渲染到相应的子组件上。完毕。

“相应”的意思是同名的组件,例如:

StockWidgetContainer => StockWidget
TagCloudContainer => TagCloud
PartyPooperListContainer => PartyPooperList

明白了吧。

(Read More)

[ng1]路由和解决项的高级技巧

本文译自Advanced routing and resolves(原文副标题:避免AngularJS控制器中的回调陷阱)。

URL路由是Web应用中不可或缺的一部分。AngularJS自带的标准路由是ngRoute。在开发Angular应用的过程中你会首先熟悉ngRoute,并且它会陪伴你很久,但最终你会发现它无法满足你的需求。

默认的路由有许多限制,使得它并不太适合复杂的应用。实际上,它只能用在最小规模的项目上。显然AngularJS团队也注意到了这个问题,已把ngRoute移出了核心模块。从AngularJS 1.2开始,使用ngRoute就必须单独加载了。

本文简介:通过AngularUI Router和嵌套的解决项(resolve)将数据加载操作移出控制器(controller),避免控制器之间的耦合和代码重复。

(Read More)

[vagrant]解决vagrant up启动太慢的问题

在vagrant上使用Ubuntu时经常会出现启动过慢的问题。我的环境是MacBook Pro Mid 2015, OS X 10.11,vagrant上是Ubuntu 14.04, 使用一段时间后发现执行vagrant up时速度特别慢,查看控制台发现启动时经常出现这条消息:

cloud-init-nonet[14.57]: waiting 120 seconds for network device

搜了下发现原因是Ubuntu与Virtual Box带的Intel网卡驱动不兼容所致,改成AMD网卡驱动即可解决。 在Vagrantfile中添加以下配置即可解决(来源):

config.vm.provider "virtualbox" do |vb|
    ### Change network card to PCnet-FAST III
    # For NAT adapter
    vb.customize ["modifyvm", :id, "--nictype1", "Am79C973"]
    # For host-only adapter
    vb.customize ["modifyvm", :id, "--nictype2", "Am79C973"]
end

(Read More)

在Netgear R7000上定制dd-wrt

启用jffs

打开Web界面,进入Administration -> Management,找到”JFFS2 Support”节。默认状态下”Internal Flash Storage”应该是”Disable”的。

  1. 设置”Internal Flash Storage”为”Enable”,点击”Save”,再点击”Apply Settings”
  2. 设置”Clean Internal Flash Storage”为”Enable”,点击”Apply Settings”
  3. 此时应该能看到”Total / Free Size”处显示出了容量,例如”93.75MB / 91.33MB”
  4. 将”Clean Internal Flash Storage”改回”Disable”,点击”Save”再”Apply Settings”

启用USB

首先将USB盘插入R7000背面的USB2.0口中。我用的是一个256MB的小优盘。

打开Web界面,进入”Service” -> “USB”。然后进行以下设置:

  1. 设置”Core USB Support”为”Enable”,点击”Apply Settings”。
  2. 设置”USB Storage Support”为”Enable”,点击”Apply Settings”。
  3. 设置”Automatic Drive Mount”为”Enable”,点击”Apply Settings”。

此时通过ssh进入命令行,输入mount命令应该能看到优盘(通常为/dev/sda1)被mount到了/tmp/mnt/sda1。如果优盘不是ext2系统,可以通过fdiskmke2fs命令重新分区并格式化。

最后回到Web界面,将/dev/sda1的UUID(在Web界面上可以看到)填入”Mount this partition to /opt”中,以便路由器启动时能够自动挂载。

安装opkg

Kong的dd-wrt已经自带了opkg,只不过需要在启用USB之后安装一下。将USB挂载到/opt之后,运行

bootstrap

简单回答几个问题即可完成opkg的安装。

安装结束之后,打开/opt/etc/opkg.conf,填写以下内容:

src/gz base http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/base
src/gz kernel http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/kernel
src/gz luci http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/luci
src/gz management http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/management
src/gz packages http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/packages
src/gz routing http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/routing
src/gz targets http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/targets
src/gz telephony http://downloads.openwrt.org/snapshots/trunk/bcm53xx/generic/packages/telephony
dest root /opt
dest ram /tmp
lists_dir ext /opt/var/opkg-lists
option overlay_root /overlay
option check_signature 1

然后执行:

# opkg update
# opkg list

安装时opkg可能会报告找不到libc,只需要加上--force-depends强制安装即可。

# opkg install vim --force-depends

推荐的opkg packages

我只装了两个:

# opkg install vim
# opkg install htop

htop在执行时会报告terminal错误,可以通过以下命令解决:

export TERMINFO=/opt/usr/share/terminfo

我建了个/tmp/root/.profile文件如下:

alias vi='vim'
export TERMINFO=/opt/usr/share/terminfo

为避免重启路由器时内容丢失,可以将这个文件保存到/jffs/profile/.profile,然后通过Web界面添加一条启动命令(”Administration” -> “Commands” -> “Save Startup”):

# copy profile for shell
cp /jffs/profile/.* /tmp/root

(Read More)

Linksys E4200v2刷OpenWRT小记

几年前买过一台Linksys E4200。E4200有两个版本:rev1和rev2。熟悉dd-wrt的人可能知道, E4200v1使用的是Broadcom芯片,支持dd-wrt,但到了rev2就换成了Marvell芯片,不再支持dd-wrt,因此没法刷固件了。 很可惜,我购买时rev1已经断货,只好买了无法刷固件的rev2。

今天偶然查到,OpenWRT已经提供了E4200v2的支持,于是决定尝试一下。

刷机很容易,去设备页面上给出的链接下载openwrt-kirkwood-linksys-viper-squashfs-factory.bin, 然后连到路由器的固件升级页面升级即可。

刷机之后需要注意的几点(给熟悉dd-wrt的人):

  • OpenWRT的默认地址是192.168.1.1
  • OpenWRT默认不提供Web界面,首次登录只能通过SSH方式。用户名为root,无密码。请在登录之后使用passwd命令设置密码。
  • 连上Internet之后(我通过已有router使用DHCP连的,若需要PPPoE请参考OpenWRT官方文档),即可用以下命令安装web界面:

    opkg update
    opkg install luci               # 安装Web界面
    opkg install luci-ssl           # 安装SSL
    /etc/init.d/uhttpd start        # 启动Web界面
    /etc/init.d/uhttpd enable       # 设置Web界面自动启动
    
  • 该固件仅支持802.11n,不支持a/b/g。如果出现Wifi接口无法启动的故障,请自行编辑/etc/config/wireless,在相应的wifi-device节中添加option hwmode '11n'以强行设置网卡为802.11n。

(Read More)

A script that changes MAC address

Here is a script that can change your MAC address automatically. Just save it as ~/bin/macchange and add ~/bin to your path. Tested on Mac OSX Yosemite.

Type macchnage to change MAC address to a random one. Type macchange restore to restore MAC address to origin.

if [[ $1 == 'restore' ]]
then
  action='restored'
  mac=$(cat ~/bin/mac.origin)
else
  action='changed'
  mac=$(openssl rand -hex 6 | sed 's/\(..\)/\1:/g; s/.$//')
fi

sudo ifconfig en0 ether $mac

echo $action MAC to $mac

ifconfig en0

(Read More)

[python]cx_Oracle安装笔记

要安装cx_Oracle包,需要首先下载Oracle的客户端库文件和头文件。访问OTN,下载相应操作系统的Instant Client Basic Package和SDK Package。64位Linux对应的文件名分别为instantclient-basic-linux.x64-12.1.0.2.0.zipinstantclient-sdk-linux.x64-12.1.0.2.0.zip

(Read More)