beego中使用fis
Tag beego, fis, on by view 9017

前段时间接触到了fis,后来发现它正是我所寻找的一类前端工具。之前在byvoid大神的博客上看到前端html源码中引用的js和css都是在文件名后面附加了随机串。如/css/style-882e60051fc11fd2558e888585fc3950.css。我感觉这个做法应该有他的深意。接触fis后才知道,文件md5映射之后可以在服务器端开启静态文件永久缓存,如此一来可以最大化利用浏览器的缓存机制,起到加快页面加载速度节省流量的效果。由于md5映射的文件名是唯一的,所以不用担心缓存导致的前端问题。这一技术在许多其他的网站上也有用到,例如百度、twitter等,其中fis就是出自百度,据fis文档介绍,其中某些创意是受twitter启发的。

最近一直在用beego做项目,于是打算将fis的md5映射机制迁移到beego上来,fis官网文档上介绍了fis在go web的实现demo,不过它是基于martini框架的,在多番查阅文档后,我觉得若是抛开模版内的资源文件自动打包这一功能单纯实现md5映射,我能够自己将其在beego上实现。

fis中带md5映射的前端资源全部记录于map.json文件中,fis项目编译后会自动生成map.json文件,示例如下

{
    "res": {
        "js/global.js": {
            "uri": "/static/js/global_f39ad61.js",
            "type": "js"
        },
        "js/user.js": {
            "uri": "/static/js/user_42dbc3b.js",
            "type": "js"
        },
        "octicons/octicons.scss": {
            "uri": "/static/octicons/octicons_1b828d3.css",
            "type": "css"
        },
        "sass/index.scss": {
            "uri": "/static/css/index_b855d1c.css",
            "type": "css"
        },
        "sass/login.scss": {
            "uri": "/static/css/login_c8abcc0.css",
            "type": "css"
        },
        "sass/register.scss": {
            "uri": "/static/css/register_b76a400.css",
            "type": "css"
        },
        "sass/style.scss": {
            "uri": "/static/css/style_462f7a1.css",
            "type": "css"
        }
    },
    "pkg": {}
}

这其中"res"项就是资源映射表,"js/global.js"以及"js/global.js"等是编译前的文件,即fis项目源文件,而"/static/js/global_f39ad61.js"以及"/static/octicons/octicons_1b828d3.css"等是编译后的文件,网站应当加载编译后的文件,而编译后的文件名是变动的,每次修改源文件并编译后,编译后的文件名md5值便会变化,不过编译前的文件名是不变的,因此,思路是通过编译前文件名得到对应的编译后的文件名,然后加载到网页。beego实现如下:

在工具包utils里有

package utils

import (
	"fmt"
	"github.com/astaxie/beego"
	"github.com/gogather/com"
	"html/template"
)

// fis map
func Fis(key string) template.HTML {
	var text string
	content := loadMap()
	json, _ := com.JsonDecode(content)
	json = json.(map[string]interface{})["res"]
	if fileMap, ok := json.(map[string]interface{}); !ok {
		fmt.Println("map.json id illeage!")
	} else {
		for tmpKey, views := range fileMap {
			uri, ok := views.(map[string]interface{})["uri"].(string)
			if !ok {
				fmt.Println("error in map.json")
			}

			fileType, ok := views.(map[string]interface{})["type"].(string)
			if !ok {
				fmt.Println("error in map.json")
			}

			if tmpKey == key {
				if fileType == "css" {
					text = `<link rel="stylesheet" href="` + uri + `">`
				} else if fileType == "js" {
					text = `<script src="` + uri + `"></script>`
				}
			}
		}
	}

	return template.HTML(text)
}

// load map.json
func loadMap() string {
	mapPath := beego.AppConfig.String("static_map")
	mapContent := com.ReadFile(mapPath)
	return mapContent
}

其中Fis函数便是由编译前的文件名查找编译后的文件名。接下来是注册模版函数

beego.AddFuncMap("asset", utils.Fis)

然后你就可以在模版中这样引入js或者css文件了

{{template "inc/header.tpl" .}}
{{asset "sass/login.scss"}}
	<div class="info">&nbsp</div>
	<div class="login">
		<form action="/login">
			<ul>
				<li><label for="">用户名</label><input type="text" name="username" id=""></li>
				<li><label for="">密码</label><input type="password" name="password" id=""></li>
				<li class="login-btns">
					<button class="btn">{{i18n "login"}}</button>
					<a class="btn oauth-login" href="https://github.com/login/oauth/authorize?client_id={{.github_client_id}}&scope=user,public_repo" target="_blank"><span class="octicon octicon-logo-github"></span>登录</a>
				</li>
			</ul>
		</form>
	</div>
{{asset "js/user.js"}}
{{template "inc/footer.tpl" .}}

其中

{{asset "sass/login.scss"}}

便是引入"sass/login.scss"对应的编译后的css文件。

如此,便实现了利用fis的md5映射功能,现在可以放心开启js和css的强制缓存了。最后附上我自己的项目地址供大家借鉴https://github.com/duguying/ojsite 。


用github登录,oauth开发
Tag github, oauth, on by view 8785

最近做的oj项目的网站子项目中要使用到“用github登录”这一功能,也就是oauth,于是研究了一番。

github的oauth验证的过程如下:

用户访问登录验证接入口

https://github.com/login/oauth/authorize?client_id=xxxxxxxxxxxxxxxxxx&scope=user,public_repo     

其中client_id由开发者在github网站上申请,无限制。
registor_github_oauth.png
申请成功后,获取client_id和client_secret
get_github_oauth_id_secret.png

用户访问上面的url之后,github会让其跳转到你预定的url,并且带上code参数,例如

http://oj.duguying.net/oauth/github?code=xxxxxxxxxxxxxxxxxx 
   

然后,开发者可以通过code,client_id以及client_secret这三个参数获取用户的access_token即用户身份标识,请求如下

https://github.com/login/oauth/access_token?client_id=xxxxxxxxxxxxxxxxxxx&client_secret=xxxxxxxxxxxxxxxxx&code=xxxxxxxxxxxxxxxxxxx 

这个请求将会返回如下内容 

access_token=xxxxxxxxxxxxxxxxxxxxxxxxx&scope=public_repo%2Cuser&token_type=bearer 

有了access_token之后,只需要通过如下请求就可以获取用户信息

https://api.github.com/user?access_token=xxxxxxxxxxxxxxxxxxxxxxxxx 

返回的信息将会是json格式。注意整个请求过程中都是使用GET请求。只要理解了oauth验证过程,如此就很容易编程实现了。

最后,附上我自己用golang实现的github的oauth验证库https://github.com/gogather/oauth


texlive中文书签乱码
Tag texlive, pdf, 中文, 书签, 乱码, on by view 8136

一个纠结了两天的问题,我之前在ctex环境下的latex项目迁移到texlive环境出现的问题。我之前的项目是gbk编码的,用ctex环境编译,因此,也只能够支持windows环境,故而,我将其转移到了texlive环境编写,字符集也由原来的gbk变为了utf8,这时出现问题了,起初解决书签乱码的方法是在编译过程中将生成的bachelor.out文件的编码由原来的gbk转为unicode,使用的是一个命令行工具gbk2uni.exe,可是现在全部变为utf8格式了out文件也不再是gbk,原来的转换方法无效了,后来也试着吧utf8格式的out文件转为unicode格式,可是还是无效,纠结很久,解决方法如下。

原文档头部如下

\documentclass{article}    
\usepackage{amsmath,amssymb}    
\usepackage{latexsym}    
\usepackage{CJK}    
\usepackage{listings,xcolor}    
\usepackage{graphicx}    
\usepackage{titlesec}    
\usepackage[dvipdfm,    
            pdfstartview=FitH,    
            CJKbookmarks=true,    
            bookmarksnumbered=true,    
            bookmarksopen=true,    
            colorlinks=true, %注释掉此项则交叉引用为彩色边框(将colorlinks和pdfborder同时注释掉)    
            %pdfborder=001,   %注释掉此项则交叉引用为彩色边框    
            citecolor=magenta,% magenta , cyan    
            linkcolor=blue,    
            linktocpage=true,    
            ]{hyperref}       % hyperref 宏包通常要求放在导言区的最后!!!    
\usepackage{titletoc}

修改为

\documentclass{ctexartutf8}
\usepackage{amsmath,amssymb}
\usepackage{latexsym}
\usepackage{CJKutf8}
\usepackage{listings,xcolor}
\usepackage{graphicx}
\usepackage{titlesec}

\usepackage[unicode,dvipdfm,
            pdfstartview=FitH,
            colorlinks=true, %注释掉此项则交叉引用为彩色边框(将colorlinks和pdfborder同时注释掉)
            %pdfborder=001,   %注释掉此项则交叉引用为彩色边框
            citecolor=magenta,% magenta , cyan
            linkcolor=blue,
            linktocpage=true,
            ]{hyperref}       % hyperref 宏包通常要求放在导言区的最后!!!
\usepackage{titletoc}

其中主要是将CJK包改为CJKutf8,另外原来需要开启CJKbookmark=true这些都不要了,当然\documentclass需要改为支持CJKutf8的格式,比如ctexartutf8等。

这个问题的的确确困扰了我至少两天的时间,最终还是在google上搜索错误信息! Argument of \HyPsd@GetTwoBytes has an extra }.找到一封邮件(http://lists.ffii.org/pipermail/cjk/2007-February/001832.html),这才恍然大悟。


windows服务注册工具nssm
Tag nssm, windows, 服务, 注册, on by view 8695

在windows系统上注册一个服务通常你要这么做:

首先,如果这个服务程序是你写的话,你必须在程序中编写ServiceMain服务主函数用来启动服务,并且要在程序中注册服务启动函数,函数原型如下。

VOID WINAPI ServiceMain(
  DWORD dwArgc,
  LPTSTR* lpszArgv
);

然后,你需要修改注册表相关信息,在注册表项"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\"中自动增加项[服务名],并在其下成功添加各个键值:

"DisplayName"   =服务显示名     (字符串值)
"Description"      =服务描述       (字符串值)
"ImagePath"       =应用程序路径   (可扩充字符串值)
"ObjectName"    ="LocalSystem"  (字符串值)
"Type"                =10(16进制)     (dword值)
"Start"                =2(16进制)      (dword值)
"ErrorControl"     =1(16进制)      (dword值)

或者直接执行instsrv [服务名] [应用程序路径],自动添加注册表信息。(不过貌似只有服务器版的windows才有instsrv命令)

完成上述操作后,如果不出意外你可以在服务管理器services.msc中可以看到你的服务。当然你如果想卸载服务,至少得把上面的第二步反过来做一遍,即清理注册表。

现在有一个更好的工具可以完成这项任务,nssm

nssm是一个命令行工具,也支持gui。

nssm install <ServerName> <Program Path>  #安装
nssm remove <ServerName> confirm          #卸载

nssm_usage_demo.png
命令行使用

nssm_gui_usage_install.png
GUI使用(安装)

nssm_gui_usage_remove.png
GUI使用(卸载)

使用nssm来安装windows服务是不需要主程序中注册服务的,也就是说想将一个程序变为服务程序有了nssm后你无需修改代码。


64位linux系统,系统调用表
Tag syscall, linux, x64, 64位, 系统调用, on by view 2133

Linux 3.2.0-33, x86_64

Note: 64-bit x86 uses syscall instead of interrupt 0x80. The result value will be in %rax

To find the implementation of a system call, grep the kernel tree for SYSCALL_DEFINE.\?(syscall,
For example, to find the read system call:

illusion:/usr/src/linux-source-3.2.0$ grep -rA3 'SYSCALL_DEFINE.\?(read,' *
fs/read_write.c:SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
fs/read_write.c-{
fs/read_write.c-        struct file *file;
fs/read_write.c-        ssize_t ret = -EBADF;

The results show that the implementation is in fs/read_write.c and that it takes 3 arguments (thus SYSCALL_DEFINE3).

Linux Cross Reference is another good tool for finding information about system calls.

By the way, the system call numbers are different for 32-bit x86. A system call table for i386 (32-bit) can be found at  http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.htm


%rax System call %rdi %rsi %rdx %rcx %r8 %r9
0 sys_read unsigned int fd char *buf size_t count      
1 sys_write unsigned int fd const char *buf size_t count      
2 sys_open const char *filename int flags int mode      
3 sys_close unsigned int fd          
4 sys_stat const char *filename struct stat *statbuf        
5 sys_fstat unsigned int fd struct stat *statbuf        
6 sys_lstat fconst char *filename struct stat *statbuf        
7 sys_poll struct poll_fd *ufds unsigned int nfds long timeout_msecs      
8 sys_lseek unsigned int fd off_t offset unsigned int origin      
9 sys_mmap unsigned long addr unsigned long len unsigned long prot unsigned long flags unsigned long fd unsigned long off
10 sys_mprotect unsigned long start size_t len unsigned long prot      
11 sys_munmap unsigned long addr size_t len        
12 sys_brk unsigned long brk          
13 sys_rt_sigaction int sig const struct sigaction *act struct sigaction *oact size_t sigsetsize    
14 sys_rt_sigprocmask int how sigset_t *nset sigset_t *oset size_t sigsetsize    
15 sys_rt_sigreturn unsigned long __unused          
16 sys_ioctl unsigned int fd unsigned int cmd unsigned long arg      
17 sys_pread64 unsigned long fd char *buf size_t count loff_t pos    
18 sys_pwrite64 unsigned int fd const char *buf size_t count loff_t pos    
19 sys_readv unsigned long fd const struct iovec *vec unsigned long vlen      
20 sys_writev unsigned long fd const struct iovec *vec unsigned long vlen      
21 sys_access const char *filename int mode        
22 sys_pipe int *filedes          
23 sys_select int n fd_set *inp fd_set *outp fd_set*exp struct timeval *tvp  
24 sys_sched_yield            
25 sys_mremap unsigned long addr unsigned long old_len unsigned long new_len unsigned long flags unsigned long new_addr  
26 sys_msync unsigned long start size_t len int flags      
27 sys_mincore unsigned long start size_t len unsigned char *vec      
28 sys_madvise unsigned long start size_t len_in int behavior      
29 sys_shmget key_t key size_t size int shmflg      
30 sys_shmat int shmid char *shmaddr int shmflg      
31 sys_shmctl int shmid int cmd struct shmid_ds *buf      
32 sys_dup unsigned int fildes          
33 sys_dup2 unsigned int oldfd unsigned int newfd        
34 sys_pause            
35 sys_nanosleep struct timespec *rqtp struct timespec *rmtp        
36 sys_getitimer int which struct itimerval *value        
37 sys_alarm unsigned int seconds          
38 sys_setitimer int which struct itimerval *value struct itimerval *ovalue      
39 sys_getpid            
40 sys_sendfile int out_fd int in_fd off_t *offset size_t count    
41 sys_socket int family int type int protocol      
42 sys_connect int fd struct sockaddr *uservaddr int addrlen      
43 sys_accept int fd struct sockaddr *upeer_sockaddr int *upeer_addrlen      
44 sys_sendto int fd void *buff size_t len unsigned flags struct sockaddr *addr int addr_len
45 sys_recvfrom int fd void *ubuf size_t size unsigned flags struct sockaddr *addr int *addr_len
46 sys_sendmsg int fd struct msghdr *msg unsigned flags      
47 sys_recvmsg int fd struct msghdr *msg unsigned int flags      
48 sys_shutdown int fd int how        
49 sys_bind int fd struct sokaddr *umyaddr int addrlen      
50 sys_listen int fd int backlog        
51 sys_getsockname int fd struct sockaddr *usockaddr int *usockaddr_len      
52 sys_getpeername int fd struct sockaddr *usockaddr int *usockaddr_len      
53 sys_socketpair int family int type int protocol int *usockvec    
54 sys_setsockopt int fd int level int optname char *optval int optlen  
55 sys_getsockopt int fd int level int optname char *optval int *optlen  
56 sys_clone unsigned long clone_flags unsigned long newsp void *parent_tid void *child_tid    
57 sys_fork            
58 sys_vfork            
59 sys_execve const char *filename const char *const argv[] const char *const envp[]      
60 sys_exit int error_code          
61 sys_wait4 pid_t upid int *stat_addr int options struct rusage *ru    
62 sys_kill pid_t pid int sig        
63 sys_uname struct old_utsname *name          
64 sys_semget key_t key int nsems int semflg      
65 sys_semop int semid struct sembuf *tsops unsigned nsops      
66 sys_semctl int semid int semnum int cmd union semun arg    
67 sys_shmdt char *shmaddr          
68 sys_msgget key_t key int msgflg        
69 sys_msgsnd int msqid struct msgbuf *msgp size_t msgsz int msgflg    
70 sys_msgrcv int msqid struct msgbuf *msgp size_t msgsz long msgtyp int msgflg  
71 sys_msgctl int msqid int cmd struct msqid_ds *buf      
72 sys_fcntl unsigned int fd unsigned int cmd unsigned long arg      
73 sys_flock unsigned int fd unsigned int cmd        
74 sys_fsync unsigned int fd          
75 sys_fdatasync unsigned int fd          
76 sys_truncate const char *path long length        
77 sys_ftruncate unsigned int fd unsigned long length        
78 sys_getdents unsigned int fd struct linux_dirent *dirent unsigned int count      
79 sys_getcwd char *buf unsigned long size        
80 sys_chdir const char *filename          
81 sys_fchdir unsigned int fd          
82 sys_rename const char *oldname const char *newname        
83 sys_mkdir const char *pathname int mode        
84 sys_rmdir const char *pathname          
85 sys_creat const char *pathname int mode        
86 sys_link const char *oldname const char *newname        
87 sys_unlink const char *pathname          
88 sys_symlink const char *oldname const char *newname        
89 sys_readlink const char *path char *buf int bufsiz      
90 sys_chmod const char *filename mode_t mode        
91 sys_fchmod unsigned int fd mode_t mode        
92 sys_chown const char *filename uid_t user git_t group      
93 sys_fchown unsigned int fd uid_t user git_t group      
94 sys_lchown const char *filename uid_t user git_t group      
95 sys_umask int mask          
96 sys_gettimeofday struct timeval *tv struct timezone *tz        
97 sys_getrlimit unsigned int resource struct rlimit *rlim        
98 sys_getrusage int who struct rusage *ru        
99 sys_sysinfo struct sysinfo *info          
100 sys_times struct sysinfo *info          
101 sys_ptrace long request long pid unsigned long addr unsigned long data    
102 sys_getuid            
103 sys_syslog int type char *buf int len      
104 sys_getgid            
105 sys_setuid uid_t uid          
106 sys_setgid git_t gid          
107 sys_geteuid            
108 sys_getegid            
109 sys_setpgid pid_t pid pid_t pgid        
110 sys_getppid            
111 sys_getpgrp            
112 sys_setsid            
113 sys_setreuid uid_t ruid uid_t euid        
114 sys_setregid git_t rgid gid_t egid        
115 sys_getgroups int gidsetsize gid_t *grouplist        
116 sys_setgroups int gidsetsize gid_t *grouplist        
117 sys_setresuid uid_t *ruid uid_t *euid uid_t *suid      
118 sys_getresuid uid_t *ruid uid_t *euid uid_t *suid      
119 sys_setresgid gid_t rgid gid_t egid gid_t sgid      
120 sys_getresgid git_t *rgid git_t *egid git_t *sgid      
121 sys_getpgid pid_t pid          
122 sys_setfsuid uid_t uid          
123 sys_setfsgid gid_t gid          
124 sys_getsid pid_t pid          
125 sys_capget cap_user_header_t header cap_user_data_t dataptr        
126 sys_capset cap_user_header_t header const cap_user_data_t data        
127 sys_rt_sigpending sigset_t *set size_t sigsetsize        
128 sys_rt_sigtimedwait const sigset_t *uthese siginfo_t *uinfo const struct timespec *uts size_t sigsetsize    
129 sys_rt_sigqueueinfo pid_t pid int sig siginfo_t *uinfo      
130 sys_rt_sigsuspend sigset_t *unewset size_t sigsetsize        
131 sys_sigaltstack const stack_t *uss stack_t *uoss        
132 sys_utime char *filename struct utimbuf *times        
133 sys_mknod const char *filename int mode unsigned dev      
134 sys_uselib NOT IMPLEMENTED          
135 sys_personality unsigned int personality          
136 sys_ustat unsigned dev struct ustat *ubuf        
137 sys_statfs const char *pathname struct statfs *buf        
138 sys_fstatfs unsigned int fd struct statfs *buf        
139 sys_sysfs int option unsigned long arg1 unsigned long arg2      
140 sys_getpriority int which int who        
141 sys_setpriority int which int who int niceval      
142 sys_sched_setparam pid_t pid struct sched_param *param        
143 sys_sched_getparam pid_t pid struct sched_param *param        
144 sys_sched_setscheduler pid_t pid int policy struct sched_param *param      
145 sys_sched_getscheduler pid_t pid          
146 sys_sched_get_priority_max int policy          
147 sys_sched_get_priority_min int policy          
148 sys_sched_rr_get_interval pid_t pid struct timespec *interval        
149 sys_mlock unsigned long start size_t len        
150 sys_munlock unsigned long start size_t len        
151 sys_mlockall int flags          
152 sys_munlockall            
153 sys_vhangup            
154 sys_modify_ldt int func void *ptr unsigned long bytecount      
155 sys_pivot_root const char *new_root const char *put_old        
156 sys__sysctl struct __sysctl_args *args          
157 sys_prctl int option unsigned long arg2 unsigned long arg3 unsigned long arg4   unsigned long arg5
158 sys_arch_prctl struct task_struct *task int code unsigned long *addr      
159 sys_adjtimex struct timex *txc_p          
160 sys_setrlimit unsigned int resource struct rlimit *rlim        
161 sys_chroot const char *filename          
162 sys_sync            
163 sys_acct const char *name          
164 sys_settimeofday struct timeval *tv struct timezone *tz        
165 sys_mount char *dev_name char *dir_name char *type unsigned long flags void *data  
166 sys_umount2 const char *target int flags        
167 sys_swapon const char *specialfile int swap_flags        
168 sys_swapoff const char *specialfile          
169 sys_reboot int magic1 int magic2 unsigned int cmd void *arg    
170 sys_sethostname char *name int len        
171 sys_setdomainname char *name int len        
172 sys_iopl unsigned int level struct pt_regs *regs        
173 sys_ioperm unsigned long from unsigned long num int turn_on      
174 sys_create_module REMOVED IN Linux 2.6          
175 sys_init_module void *umod unsigned long len const char *uargs      
176 sys_delete_module const chat *name_user unsigned int flags        
177 sys_get_kernel_syms REMOVED IN Linux 2.6          
178 sys_query_module REMOVED IN Linux 2.6          
179 sys_quotactl unsigned int cmd const char *special qid_t id void *addr    
180 sys_nfsservctl NOT IMPLEMENTED          
181 sys_getpmsg NOT IMPLEMENTED          
182 sys_putpmsg NOT IMPLEMENTED          
183 sys_afs_syscall NOT IMPLEMENTED          
184 sys_tuxcall NOT IMPLEMENTED          
185 sys_security NOT IMPLEMENTED          
186 sys_gettid            
187 sys_readahead int fd loff_t offset size_t count      
188 sys_setxattr const char *pathname const char *name const void *value size_t size int flags  
189 sys_lsetxattr const char *pathname const char *name const void *value size_t size int flags  
190 sys_fsetxattr int fd const char *name const void *value size_t size int flags  
191 sys_getxattr const char *pathname const char *name void *value size_t size    
192 sys_lgetxattr const char *pathname const char *name void *value size_t size    
193 sys_fgetxattr int fd const har *name void *value size_t size    
194 sys_listxattr const char *pathname char *list size_t size      
195 sys_llistxattr const char *pathname char *list size_t size      
196 sys_flistxattr int fd char *list size_t size      
197 sys_removexattr const char *pathname const char *name        
198 sys_lremovexattr const char *pathname const char *name        
199 sys_fremovexattr int fd const char *name        
200 sys_tkill pid_t pid ing sig        
201 sys_time time_t *tloc          
202 sys_futex u32 *uaddr int op u32 val struct timespec *utime u32 *uaddr2 u32 val3
203 sys_sched_setaffinity pid_t pid unsigned int len unsigned long *user_mask_ptr      
204 sys_sched_getaffinity pid_t pid unsigned int len unsigned long *user_mask_ptr      
205 sys_set_thread_area NOT IMPLEMENTED. Use arch_prctl          
206 sys_io_setup unsigned nr_events aio_context_t *ctxp        
207 sys_io_destroy aio_context_t ctx          
208 sys_io_getevents aio_context_t ctx_id long min_nr long nr struct io_event *events    
209 sys_io_submit aio_context_t ctx_id long nr struct iocb **iocbpp      
210 sys_io_cancel aio_context_t ctx_id struct iocb *iocb struct io_event *result      
211 sys_get_thread_area NOT IMPLEMENTED. Use arch_prctl          
212 sys_lookup_dcookie u64 cookie64 long buf long len      
213 sys_epoll_create int size          
214 sys_epoll_ctl_old NOT IMPLEMENTED          
215 sys_epoll_wait_old NOT IMPLEMENTED          
216 sys_remap_file_pages unsigned long start unsigned long size unsigned long prot unsigned long pgoff unsigned long flags  
217 sys_getdents64 unsigned int fd struct linux_dirent64 *dirent unsigned int count      
218 sys_set_tid_address int *tidptr          
219 sys_restart_syscall            
220 sys_semtimedop int semid struct sembuf *tsops unsigned nsops const struct timespec *timeout    
221 sys_fadvise64 int fd loff_t offset size_t len int advice    
222 sys_timer_create const clockid_t which_clock struct sigevent *timer_event_spec timer_t *created_timer_id      
223 sys_timer_settime timer_t timer_id int flags const struct itimerspec *new_setting struct itimerspec *old_setting    
224 sys_timer_gettime timer_t timer_id struct itimerspec *setting        
225 sys_timer_getoverrun timer_t timer_id          
226 sys_timer_delete timer_t timer_id          
227 sys_clock_settime const clockid_t which_clock const struct timespec *tp        
228 sys_clock_gettime const clockid_t which_clock struct timespec *tp        
229 sys_clock_getres const clockid_t which_clock struct timespec *tp        
230 sys_clock_nanosleep const clockid_t which_clock int flags const struct timespec *rqtp struct timespec *rmtp    
231 sys_exit_group int error_code          
232 sys_epoll_wait int epfd struct epoll_event *events int maxevents int timeout    
233 sys_epoll_ctl int epfd int op int fd struct epoll_event *event    
234 sys_tgkill pid_t tgid pid_t pid int sig      
235 sys_utimes char *filename struct timeval *utimes        
236 sys_vserver NOT IMPLEMENTED          
237 sys_mbind unsigned long start unsigned long len unsigned long mode unsigned long *nmask unsigned long maxnode unsigned flags
238 sys_set_mempolicy int mode unsigned long *nmask unsigned long maxnode      
239 sys_get_mempolicy int *policy unsigned long *nmask unsigned long maxnode unsigned long addr unsigned long flags  
240 sys_mq_open const char *u_name int oflag mode_t mode struct mq_attr *u_attr    
241 sys_mq_unlink const char *u_name          
242 sys_mq_timedsend mqd_t mqdes const char *u_msg_ptr size_t msg_len unsigned int msg_prio const stuct timespec *u_abs_timeout  
243 sys_mq_timedreceive mqd_t mqdes char *u_msg_ptr size_t msg_len unsigned int *u_msg_prio const struct timespec *u_abs_timeout  
244 sys_mq_notify mqd_t mqdes const struct sigevent *u_notification        
245 sys_mq_getsetattr mqd_t mqdes const struct mq_attr *u_mqstat struct mq_attr *u_omqstat      
246 sys_kexec_load unsigned long entry unsigned long nr_segments struct kexec_segment *segments unsigned long flags    
247 sys_waitid int which pid_t upid struct siginfo *infop int options struct rusage *ru  
248 sys_add_key const char *_type const char *_description const void *_payload size_t plen    
249 sys_request_key const char *_type const char *_description const char *_callout_info key_serial_t destringid    
250 sys_keyctl int option unsigned long arg2 unsigned long arg3 unsigned long arg4 unsigned long arg5  
251 sys_ioprio_set int which int who int ioprio      
252 sys_ioprio_get int which int who        
253 sys_inotify_init            
254 sys_inotify_add_watch int fd const char *pathname u32 mask      
255 sys_inotify_rm_watch int fd __s32 wd        
256 sys_migrate_pages pid_t pid unsigned long maxnode const unsigned long *old_nodes const unsigned long *new_nodes    
257 sys_openat int dfd const char *filename int flags int mode    
258 sys_mkdirat int dfd const char *pathname int mode      
259 sys_mknodat int dfd const char *filename int mode unsigned dev    
260 sys_fchownat int dfd const char *filename uid_t user gid_t group int flag  
261 sys_futimesat int dfd const char *filename struct timeval *utimes      
262 sys_newfstatat int dfd const char *filename struct stat *statbuf int flag    
263 sys_unlinkat int dfd const char *pathname int flag      
264 sys_renameat int oldfd const char *oldname int newfd const char *newname    
265 sys_linkat int oldfd const char *oldname int newfd const char *newname int flags  
266 sys_symlinkat const char *oldname int newfd const char *newname      
267 sys_readlinkat int dfd const char *pathname char *buf int bufsiz    
268 sys_fchmodat int dfd const char *filename mode_t mode      
269 sys_faccessat int dfd const char *filename int mode      
270 sys_pselect6 int n fd_set *inp fd_set *outp fd_set *exp struct timespec *tsp void *sig
271 sys_ppoll struct pollfd *ufds unsigned int nfds struct timespec *tsp const sigset_t *sigmask size_t sigsetsize  
272 sys_unshare unsigned long unshare_flags          
273 sys_set_robust_list struct robust_list_head *head size_t len        
274 sys_get_robust_list int pid struct robust_list_head **head_ptr size_t *len_ptr      
275 sys_splice int fd_in loff_t *off_in int fd_out loff_t *off_out size_t len unsigned int flags
276 sys_tee int fdin int fdout size_t len unsigned int flags    
277 sys_sync_file_range long fd loff_t offset loff_t bytes long flags    
278 sys_vmsplice int fd const struct iovec *iov unsigned long nr_segs unsigned int flags    
279 sys_move_pages pid_t pid unsigned long nr_pages const void **pages const int *nodes int *status int flags
280 sys_utimensat int dfd const char *filename struct timespec *utimes int flags    
281 sys_epoll_pwait int epfd struct epoll_event *events int maxevents int timeout const sigset_t *sigmask size_t sigsetsize
282 sys_signalfd int ufd sigset_t *user_mask size_t sizemask      
283 sys_timerfd_create int clockid int flags        
284 sys_eventfd unsigned int count          
285 sys_fallocate long fd long mode loff_t offset loff_t len    
286 sys_timerfd_settime int ufd int flags const struct itimerspec *utmr struct itimerspec *otmr    
287 sys_timerfd_gettime int ufd struct itimerspec *otmr        
288 sys_accept4 int fd struct sockaddr *upeer_sockaddr int *upeer_addrlen int flags    
289 sys_signalfd4 int ufd sigset_t *user_mask size_t sizemask int flags    
290 sys_eventfd2 unsigned int count int flags        
291 sys_epoll_create1 int flags          
292 sys_dup3 unsigned int oldfd unsigned int newfd int flags      
293 sys_pipe2 int *filedes int flags        
294 sys_inotify_init1 int flags          
295 sys_preadv unsigned long fd const struct iovec *vec unsigned long vlen unsigned long pos_l unsigned long pos_h  
296 sys_pwritev unsigned long fd const struct iovec *vec unsigned long vlen unsigned long pos_l unsigned long pos_h  
297 sys_rt_tgsigqueueinfo pid_t tgid pid_t pid int sig siginfo_t *uinfo    
298 sys_perf_event_open struct perf_event_attr *attr_uptr pid_t pid int cpu int group_fd unsigned long flags  
299 sys_recvmmsg int fd struct msghdr *mmsg unsigned int vlen unsigned int flags struct timespec *timeout  
300 sys_fanotify_init unsigned int flags unsigned int event_f_flags        
301 sys_fanotify_mark long fanotify_fd long flags __u64 mask long dfd long pathname  
302 sys_prlimit64 pid_t pid unsigned int resource const struct rlimit64 *new_rlim struct rlimit64 *old_rlim    
303 sys_name_to_handle_at int dfd const char *name struct file_handle *handle int *mnt_id int flag  
304 sys_open_by_handle_at int dfd const char *name struct file_handle *handle int *mnt_id int flags  
305 sys_clock_adjtime clockid_t which_clock struct timex *tx        
306 sys_syncfs int fd          
307 sys_sendmmsg int fd struct mmsghdr *mmsg unsigned int vlen unsigned int flags    
308 sys_setns int fd int nstype        
309 sys_getcpu unsigned *cpup unsigned *nodep struct getcpu_cache *unused      
310 sys_process_vm_readv pid_t pid const struct iovec *lvec unsigned long liovcnt const struct iovec *rvec unsigned long riovcnt unsigned long flags
311 sys_process_vm_writev pid_t pid const struct iovec *lvec unsigned long liovcnt const struct iovcc *rvec unsigned long riovcnt unsigned long flags

转自 http://blog.rchapman.org/post/36801038863/linux-system-call-table-for-x86-64




php-fpm网站目录权限配置
Tag php-fpm, 权限, nginx, on by view 7074

今天本来想搭建一个现成的php网站系统,打算使用nginx+php-fpm来搭建。可是,问题来了……

将php文件放置于/usr/local/nginx/html下,一切正常,我将php文件放置于其它目录却出问题了,File not found. ,nginx配置文件没有任何问题,配置文件如下:

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

        access_log  logs/rex_test.log;

        #root         /tmpwww/hello;
        root          /tmpwww/test;

        location / {
            index  index.html index.htm;
        }

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
    }
}

配置文件是不存在错误的,各种百度谷歌之后,觉得问题应该是出在网站目录权限上,特地测试了一下,手动创建了/tmpwww文件夹,在其下手动创建hello文件夹,其下放置info.php文件:

<?php
phpinfo();

访问,正常。为了重现错误,我在tmpwww文件夹下面创建test文件夹,其下info.php。正常,tree -p查看我原来不能正常访问的网站目录,发现部分层级的目录是drwxr-x---,你妹这不是group连读的权限都没有么。chmod 750 /tmpwww/test将/tmpwww/test也改为了drwxr-x---,nginx配置文件改为如上(即网站根切换到/tmpwww/test),File not found. 再次出现,故障重现了。

php_fpm_permission_debug.png

总结,对于php-fpm,网站目录必须至少可读,并且其路径中涉及到的各层级目录也必须保证至少可读,只有这样php-fpm及其worker进程才能访问到网站的根目录。


二叉树非递归解汉诺塔
Tag 汉诺塔, 非递归, 算法, 数据结构, 二叉树, on by view 6477

解汉诺塔最常见的方法是递归法,记得上数据结构那门课的时候老师说过,递归法通常情况下都能够找到一种非递归的方法来实现,汉诺塔也有非递归的方法解决。

递归方法:

首先把三根柱子按顺序排成品字型,把所有的圆盘按从大到小的顺序放在柱子A上,根据圆盘的数量确定柱子的排放顺序:若n为偶数,按顺时针方向依次摆放 A B C;若n为奇数,按顺时针方向依次摆放 A C B。

  1. 按顺时针方向把圆盘1从现在的柱子移动到下一根柱子,即当n为偶数时,若圆盘1在柱子A,则把它移动到B;若圆盘1在柱子B,则把它移动到C;若圆盘1在柱子C,则把它移动到A。

  2. 接着,把另外两根柱子上可以移动的圆盘移动到新的柱子上。即把非空柱子上的圆盘移动到空柱子上,当两根柱子都非空时,移动较小的圆盘。这一步没有明确规定移动哪个圆盘,你可能以为会有多种可能性,其实不然,可实施的行动是唯一的。

  3. 反复进行1、2操作,最后就能按规定完成汉诺塔的移动。

所以结果非常简单,就是按照移动规则向一个方向移动金片:
如3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C

非递归方法

  1. 确定起点塔、终点塔,确定层数n

  2. 若由A到C,画出其下分支

                     A→C                          1

            A→B          B→C                  2

    A→C   C→B    BA   A→C           3

  3. 中序遍历得到结果A→C, A→B, C→B, A→C, BA , B→C, A→C

tree-script.jpg
5阶汉诺塔二叉树(演算手稿)

这种非递归的方法在手工演算方面着实简易,只需列出这棵二叉树便能够迅速写出答案。哈哈,挺适合做试卷的。不过,用此方法编程从理解上到也是比较容易的,比起递归法可能代码稍多但理解较易。


初尝windows 10
Tag win10, windows, on by view 4211

前不久新版本的windows出来了,名字是windows 10,而不是大家以为的windows 9。windows 10技术预览版的iso镜像出来了,试用了一下。

总体风格继承了windows 8
Windows 10 x64-2014-10-04-19-54-34.png

开始菜单回来了
Windows 10 x64-2014-10-04-20-22-24.png

命令提示符复制可以用ctrl+c,选中无需右键了
Windows 10 x64-2014-10-04-19-56-13.png

windows modern ui支持窗口模式了
Windows 10 x64-2014-10-04-20-01-04.png

支持多桌面了
Windows 10 x64-2014-10-04-20-17-23.png

总之,外观上感觉与windows 8的风格没有太大的区别。至於内在的更新也不是一眼能够看出来的,相信随着大家逐步的使用是能够逐渐发现新版的系统的变化的。


网站中Cache的使用
Tag 构架, Cache, 网站, MVC, on by view 5731

现在的许都网站都使用MVC构架,为了应对高并发,人们通常使用基于内存存取的Cache系统作为后端减压的应对方式。在网站的后端,主要涉及业务逻辑处理和数据库查询,而数据查询许多时候在高并发的状况下成为了性能的瓶颈。本文要讨论的是Cache如何使用才能够更加合理,更加有效。

网站的MVC构架通常情况如下
mvc_structure.png
数据库(Database)处于最后端,其次是Model层,Model层是对数据库直接操作的一种封装,然后是Controller层,Controller层是专门处理业务逻辑的,获取数据是直接调用Model层中封装的各种方法,最外层是View层,负责显示数据到页面,Controller层处理完毕的的数据传到View层,由其渲染为静态页发送给用户浏览器。

构想一,将Cache用于Model层中
cache_in_model.png
Cache用于Model层是将查询到的数据放置到Cache中,从而避免下次同样的数据需要再次去数据库执行SQL语句查询,而是直接从Cache中更快的读取数据(理论上某些SQL查询非常耗时,这样Cache效果更明显)。

// 通过id获取文章-cached
func GetArticle(id int) (Article, error) {
	var err error
	var art Article

	cache := config.GetCache("GetArticle.id." + fmt.Sprintf("%d", id))
	if cache != nil { // check cache
		json.Unmarshal([]byte(cache.(string)), &art)
		return art, nil
	} else {
		o := orm.NewOrm()
		o.Using("default")
		art = Article{Id: id}
		err = o.Read(&art, "id")

		data, _ := utils.JsonEncode(art)
		config.SetCache("GetArticle.id."+fmt.Sprintf("%d", id), data, 600)
	}

	return art, err
}

构想二,将Cache用于Controller层,甚至View层。
cache_in_controller.png
若是将Cache用于Controller层,可以同时减轻业务逻辑处理和数据库查询。如果将Cache用于View层,甚至可以减轻模版的渲染工作,这样一来有点类似于全站静态化的感觉了,但是我并不觉得这是一个好方法,或许对于个别网站是可行的,但是对于大多数相对复杂的网站,这是完全不科学的方法。例如,一个论坛网站,某个页面有帖子正文,有回复,若是将这种页面放入Cache势必会导致不得不降低Cache过期时间,而最终的结果将会是Cache命中率极低,还不如不用Cache。

对于我来说,我更偏向于在Model层使用Cache,因为这样会更加灵活能够定向的缓存该缓存的东西,而不是像方案二中外层的缓存使得数据块不易分离。


windows live writer与wordpress通讯协议(xmlrpc)分析
Tag windows live writer, wordpress, xmlrpc, 通讯, on by view 5732

最近一直在完善自己的博客,wordpress博客不可不谓之博客系统中最完善的一个,我的博客系统也一直以wordpress为样本,向wordpress学习。相信用过wordpress的人都用过windows live writer作为自己博客的客户端。windows live writer原本是微软为live博客开发的客户端,但是现在live博客已经关停,因此windows live writer也停止了更新。作为windows系统下最佳的博客离线客户端,即便它已经停止更新,它也将会是一款经典的软件,如同xp系统一样。

最近两天的时间,我将自己的博客系统实现了与windows live writer通讯,苦于找不到有用的指导资料,折腾得很辛苦。

调试工具:
服务端:本地搭建wordpress,我的博客blog
客户端:windows live writer,chrome浏览器的Postman应用扩展

调试过程:

  1. 进入本地wordpress首页,找到xmlrpc协议入口

    <link title="RSD" rel="EditURI" type="application/rsd+xml" href="http://127.0.0.1/xmlrpc.php">

    之后的所有请求都是从这个入口上实现的。

  2. 协议检查。windows live writer连接后的第一件事请是获取到首页上的接口(title为RSD的link标签),第二件事情便是向http://127.0.0.1/xmlrpc.php发送get请求,获取到的内容大致如下:

    <?xml version="1.0" encoding="UTF-8"?><rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd">
      <service>
        <engineName>WordPress</engineName>
        <engineLink>http://wordpress.org/</engineLink>
        <homePageLink>http://127.0.0.1</homePageLink>
        <apis>
          <api name="WordPress" blogID="1" preferred="true" apiLink="http://127.0.0.1/xmlrpc" />
        </apis>
      </service>
    </rsd>
  3. 登录,发送blogger.getUsersBlogs请求【以下请求的主体均在http request的body内,并且皆为post请求】

    <?xml version="1.0" encoding="utf-8"?>
    <methodCall>
     <methodName>blogger.getUsersBlogs</methodName>
     <params>
      <param>
       <value>
        <string>ffffffabffffffce6dffffff93ffffffac29ffffffc9fffffff826ffffffdeffffffc9ffffffe43c0b763036ffffffa0fffffff3ffffffa963377716</string>
       </value>
      </param>
      <param>
       <value>
        <!-- 用户名 -->
        <string>lijun</string>
       </value>
      </param>
      <param>
       <value>
        <!-- 密码 -->
        <string>lijun</string>
       </value>
      </param>
     </params>
    </methodCall>

    响应:

    <?xml version="1.0" encoding="UTF-8"?>
    <methodResponse>
      <params>
        <param>
          <value>
            <array>
              <data>
                <value>
                  <struct>
                    <!-- 1 -->
                    <member><name>isAdmin</name><value><boolean>1</boolean></value></member>
                    <!-- homepage -->
                    <member><name>url</name><value><string>%s</string></value></member>
                    <!-- userid -->
                    <member><name>blogid</name><value><string>%d</string></value></member>
                    <!-- blogname -->
                    <member><name>blogName</name><value><string>%s</string></value></member>
                    <!-- xmlrpc url address -->
                    <member><name>xmlrpc</name><value><string>%s</string></value></member>
                  </struct>
                </value>
              </data>
            </array>
          </value>
        </param>
      </params>
    </methodResponse>

    上面的%d%s等按照自己的博客替换成相应的返回参数,遵循printf函数的格式化规则。

  4. 新建文章metaWeblog.newPost

    <?xml version="1.0" encoding="utf-8"?>
    <methodCall>
     <methodName>metaWeblog.newPost</methodName>
     <params>
      <param>
       <value>
        <string>1</string>
       </value>
      </param>
      <param>
       <value>
        <string>lijun</string>
       </value>
      </param>
      <param>
       <value>
        <string>lijun</string>
       </value>
      </param>
      <param>
       <value>
        <struct>
         <member>
          <name>title</name>
          <value>
           <string>test tag</string>
          </value>
         </member>
         <member>
          <name>description</name>
          <value>
           <string>&lt;p&gt;test tag content&lt;/p&gt;</string>
          </value>
         </member>
         <member>
          <name>mt_text_more</name>
          <value>
           <string />
          </value>
         </member>
         <member>
          <name>wp_slug</name>
          <value>
           <string />
          </value>
         </member>
         <member>
          <name>mt_basename</name>
          <value>
           <string />
          </value>
         </member>
         <member>
          <name>wp_password</name>
          <value>
           <string />
          </value>
         </member>
         <member>
          <name>categories</name>
          <value>
           <array>
            <data>
             <value>
              <string>ceshi</string>
             </value>
             <value>
              <string>tag</string>
             </value>
            </data>
           </array>
          </value>
         </member>
         <member>
          <name>mt_excerpt</name>
          <value>
           <string />
          </value>
         </member>
        </struct>
       </value>
      </param>
      <param>
       <value>
        <boolean>1</boolean>
       </value>
      </param>
     </params>
    </methodCall>

    响应:

    <?xml version="1.0" encoding="UTF-8"?>
    <methodResponse>
      <params>
        <param>
          <value>
          <!-- post id -->
          <string>%d</string>
          </value>
        </param>
      </params>
    </methodResponse>
  5. 新建分类标签请求wp.newCategory

    <?xml version="1.0" encoding="utf-8"?>
    <methodCall>
     <methodName>wp.newCategory</methodName>
     <params>
      <param>
       <value>
        <string>1</string>
       </value>
      </param>
      <param>
       <value>
        <string>lijun</string>
       </value>
      </param>
      <param>
       <value>
        <string>lijun</string>
       </value>
      </param>
      <param>
       <value>
        <struct>
         <member>
          <name>name</name>
          <value>
           <string>测试</string>
          </value>
         </member>
         <member>
          <name>parent_id</name>
          <value>
           <int>0</int>
          </value>
         </member>
        </struct>
       </value>
      </param>
     </params>
    </methodCall>

     响应:

    <?xml version="1.0" encoding="UTF-8"?>
    <methodResponse>
      <params>
        <param>
          <value>
          <!-- catalog id -->
          <int>%d</int>
          </value>
        </param>
      </params>
    </methodResponse>
  6. 新建媒体文件metaWeblog.newMediaObject【图片上传】

    <?xml version="1.0" encoding="utf-8"?>
    <methodCall>
     <methodName>metaWeblog.newMediaObject</methodName>
     <params>
      <param>
       <value>
        <string>1</string>
       </value>
      </param>
      <param>
       <value>
        <string>lijun</string>
       </value>
      </param>
      <param>
       <value>
        <string>lijun</string>
       </value>
      </param>
      <param>
       <value>
        <struct>
         <member>
          <name>name</name>
          <value>
           <string>loadfailed.png</string>
          </value>
         </member>
         <member>
          <name>type</name>
          <value>
           <string>image/png</string>
          </value>
         </member>
         <member>
          <name>bits</name>
          <value>
           <!-- base64转码的图片文件 -->
           <base64>iVBORw0KGgoAAAANSUhEUgAAAkJggg==</base64>
          </value>
         </member>
        </struct>
       </value>
      </param>
     </params>
    </methodCall>

     响应:

    <?xml version="1.0" encoding="UTF-8"?>
    <methodResponse>
      <params>
        <param>
          <value>
          <struct>
            <!-- file id -->
            <member><name>id</name><value><string>%d</string></value></member>
            <!-- file name -->
            <member><name>file</name><value><string>%s</string></value></member>
            <!-- file url -->
            <member>
              <name>url</name>
              <value><string>%s</string></value>
            </member>
            <!-- file type -->
            <member><name>type</name><value><string>%s</string></value></member>
          </struct>
          </value>
        </param>
      </params>
    </methodResponse>


协议的内容太多,如有需要还建议自己使用相关的工具进行捕捉请求,以及使用Postman捕捉响应,然后自己分析请求与响应的内容,并在自己的系统中实现它。响应部分的其他内容可以参考我的博客系统源码http://github.com/duguying/blog ,请求部分我已经打包可以直接下载