终端开发终极配置

终端是每天要用到的工具,所以一定要配置成自己顺手的,才能发挥更高的效率。iTerm2+zsh+vim是我目前用过的感觉最强大的配置方案了。

iTerm2

iTerm2是默认终端的终极替代方案,个性化、热键等方面表现非常出色,兼容性也非常好。

iTerm2

直接到其官网下载安装即可。

对于终端里的特殊字符可能有的无法显示,要安装powerline字体:

git clone https://github.com/powerline/fonts.git --depth=1
cd fonts && ./install.sh

然后在Preferences - Profiles - Text - Font里选择powerline字体就可以了。

zsh

zsh在命令补全等很多方面上比bash智能很多,首先切换到zsh:

chsh -s /bin/zsh

oh-my-zsh是一个管理zsh配置的框架,包含各种插件和主题,可用以下脚本安装:

sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

oh-my-zsh

安装完成后编辑~/.zshrc,可以编辑ZSH_THEME修改主题,或者编辑plugins增加插件,对应的文件分别在~/.oh-my-zsh/themes~/.oh-my-zsh/plugins下。

vim

spf13-vim是vim的终极配置之一,用以下脚本安装:

curl https://j.mp/spf13-vim3 -L > spf13-vim.sh && sh spf13-vim.sh

spf13-vim

配色文件在~/.vim/bundle/vim-colorschemes/colors下,指定名称修改配色:

echo colorscheme $colorscheme_name  >> ~/.vimrc.local
Read More +

macOS配置PHP开发环境

上(shí)班(xí)的时候写PHP都是在开发机上,所以公司配的电脑上一直就没有搭PHP环境。最近我预料到要写一个Web的项目,所以提前搭一下环境备用。

安装MySQL

可以直接通过homebrew安装:

brew install mysql

安装完成后第一次启动MySQL:

brew services start mysql

然后就可以用mysql_secure_installation初始化设置一下MySQL,包括root密码等等。

开机启动homebrew.mxcl.mysql.plist已经默认添加到~/Library/LaunchAgents里了,所以不用再设置了。

安装Nginx

同样Nginx也可以通过homebrew安装:

brew install nginx

安装完成后直接用nginx命令就可以启动。

但是Nginx的开机启动项并没有默认添加,我们可以手动将它添加进去:

cp /usr/local/opt/nginx/homebrew.mxcl.nginx.plist ~/Library/LaunchAgents/

配置PHP

macOS默认是安装好PHP的,所以就不想再安装其他版本了。

先编辑/private/etc/php.ini,如果没有就复制一份php.ini.default,然后配置一下时区和数据库socket:

1
2
date.timezone = "Asia/Shanghai"
pdo_mysql.default_socket = /tmp/mysql.sock

因为我要用yii框架,所以改了这一项,如果用到了MySQL的其他函数需要修改相应的mysql.default_socketmysqli.default_socket

然后编辑/private/etc/php-fpm.conf,在里面指定一下error_log的路径:

1
error_log = /usr/local/var/log/php-fpm/error.log

然后直接用php-fpm命令启动即可。

接着去配置一下/usr/local/etc/nginx/nginx.conf,将php的一段去掉注释,并修改fastcgi_param

1
2
3
4
5
6
7
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

然后执行nginx -s reload重新加载配置。

然后也可以配置一下php-fpm的开机启动,直接新建~/Library/LaunchAgents/net.php.php-fpm.plist文件:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>net.php.php-fpm</string>
<key>RunAtLoad</key>
<true/>
<key>Program</key>
<string>/usr/sbin/php-fpm</string>
</dict>
</plist>

保存后将其权限设为600即可,然后执行启动:

launchctl load ~/Library/LaunchAgents/net.php.php-fpm.plist

如果提示Service is disabled,上面的命令加上-w参数再执行就行了。

Read More +

shell脚本内的并发执行

之前有一个每周数据统计的工作,需要每周的某一天定时从多台服务器上拉取日志进行汇总生成报表。

顺序执行

最初的思路是先做一个循环,遍历每台机器并在上面执行相应的数据处理脚本,然后将处理好的数据拉取到汇总的机器上,这样逐台进行,最后进行汇总处理,写出来的脚本是类似这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
array=( \
"10.144.1.1" \
"10.144.1.2" \
"10.144.1.3" \
"10.144.1.4" \
)

for i in ${array[@]}
do
ssh $i "sh $log_dir/run.sh"
scp $i:$log_dir/log $work_dir/$i/
done

cat $work_dir/*/log | sort | uniq > $work_dir/log

这样写的执行时间大约是每台机器时间*台数+汇总时间,虽然不算快,但是凌晨一般也能执行完成。

并发执行

后来到了国庆假期期间,服务流量骤增,再加上业务改版等一系列原因,导致数据量突然增大,执行时间翻了几倍,任务大概要到下午才能完成,这样一来就会耽误白天的工作。

因为机器数量不少,分机器统计也是主要的时间消耗,因此想到既然几台机器各自的统计互不影响,可以让它们同时进行汇总工作。于是上网找了一下改进方法,改完了大致是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
array=( \
"10.144.1.1" \
"10.144.1.2" \
"10.144.1.3" \
"10.144.1.4" \
)

for i in ${array[@]}
do {
ssh $i "sh $log_dir/run.sh"
scp $i:$log_dir/log $work_dir/$i/
}&
done
wait

cat $work_dir/*/log | sort | uniq > $work_dir/log

可以发现主要的改动就在for循环的内容用{}括起来并在末尾加个&,这样就可以实现多次循环一起执行了;另外在done后面加个wait是为了等待所有的循环都执行完成后再做后面的汇总工作,否则一旦有一个循环执行完成就会往下执行了。

这样的执行时间大约是每台机器时间+汇总时间,可以看出比最初快了很多。

Read More +

ssh保持继续连接

公司开发登录堡垒机时需要使用PIN+token的方式进行认证,而且动态密码只能一次使用,因此一次要打开多个终端都要多次等待动态密码的变化才能登录。

所以听从公司同(xué)事(zhǎng)的建议,配置了一下~/.ssh/config

1
2
3
4
Host *
ControlMaster auto
ControlPath ~/.ssh/%h-%p-%r
ControlPersist yes

如果没有这个文件可以新建。其中Host项是指目标地址;ControlMaster一项会使一旦有一个连接以后,再次从其他终端连接同一个host也不必再输密码;ControlPersist一项可以一段时间不再输密码也可以登录。这样配置以后就能实现输一次密码后对于同一host不再输密码即可连接了。

Read More +

搭建Ngrok内网穿透服务

之前上开源课的时候听说可以通过外网访问局域网电脑获取文件,但由于自己家中的宽带一直不给分配公网地址,所以无法直接访问。

后来又听说可以用花生壳之类的DDNS动态解析,即使家中IP总变化也可以通过域名访问。但苦于这样的服务一般是收费的,而且又是使用第三方的服务器容易受制于人,用起来有些不爽,才一直寻找更好的方法。

近日又发现Ngrok这样的神器,可以自己搭建内网穿透服务,只用一台VPS一个域名就完美地解决了问题。其主要是在客户端与服务端之间建立端到端的隧道进行通信,用固定的域名进行访问以规避了IP变更的不便。

服务端

目前Ngrok官网上放出的2.0以上版本是付费的服务,若要自己搭建需要自行编译1.7的源码。首先将源码从GitHub上clone下来:

git clone https://github.com/inconshreveable/ngrok.git

编译

由于该服务是Go语言编写的,所以先要安装golang开发环境:

yum install golang

然后将NGROK_DOMAIN这个变量赋成要使用的域名后面要用到,例如使用如下域名,相应的也要在域名解析里将shintaku.cc*.shintaku.cc解析到这台VPS的IP上:

NGROK_DOMAIN="shintaku.cc"

使用Ngrok官方服务时,下载的客户端使用的是官方证书。我们自己编译服务端和客户端,使用自己的域名也要生成自签名证书

cd ngrok
openssl genrsa -out ngrokroot.key 2048
openssl req -x509 -new -nodes -key ngrokroot.key -subj "/CN=$NGROK_DOMAIN" -days 36500 -out ngrokroot.crt
openssl genrsa -out snakeoil.key 2048
openssl req -new -key snakeoil.key -subj "/CN=$NGROK_DOMAIN" -out snakeoil.csr
openssl x509 -req -in snakeoil.csr -days 36500 -CA ngrokroot.crt -CAkey ngrokroot.key -CAcreateserial -out snakeoil.crt 

这样就在当前目录下生成了ngrokroot.crtngrokroot.keyngrokroot.srlsnakeoil.crtsnakeoil.csrsnakeoil.key六个文件,将它们复制到相应的目录中:

cp ngrokroot.crt assets/client/tls/
cp snakeoil.crt assets/server/tls/
cp snakeoil.key assets/server/tls/

然后就可以开始编译服务端了:

make release-server

编译好的二进制文件ngrokd生成在bin目录下。

启动

ngrokd可以在其目录下直接启动,若要想全局使用这个命令可以将其移动到设了环境变量的目录下:

cp ./bin/ngrokd /usr/sbin/

可以先ngrokd -h看一下使用说明,然后就可以通过如下命令启动服务端了:

ngrokd -domain="shintaku.cc" -httpAddr=":80" -httpsAddr=":443"

启动要像上面一样加参数指定域名和端口。由于这台VPS我没有搭建Web服务,所以80和443端口没有占用,当然默认也是使用这两个端口的,这样在浏览器访问地址时也省得指定非80端口的麻烦了。出现如下信息就说明启动成功了:

[16:58:26 CST 2016/09/01] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [registry] [tun] No affinity cache specified
[16:58:26 CST 2016/09/01] [INFO] (ngrok/log.Info:112) Listening for public http connections on [::]:80
[16:58:26 CST 2016/09/01] [INFO] (ngrok/log.Info:112) Listening for public https connections on [::]:443
[16:58:26 CST 2016/09/01] [INFO] (ngrok/log.Info:112) Listening for control and proxy connections on [::]:4443
[16:58:26 CST 2016/09/01] [INFO] (ngrok/log.(*PrefixLogger).Info:83) [metrics] Reporting every 30 seconds

另外4443端口用于监听客户端,如有必要也可修改。

客户端

编译

客户端的编译和服务端类似,但要使用与服务端相同的文件。可以先在本机安装golang环境,再将VPS上的源码拷贝到本机直接用make release-client编译;也可以在VPS上加参数编译其他环境的客户端:

macOS

GOOS=darwin GOARCH=amd64 make release-client

Windows

GOOS=windows GOARCH=amd64 make release-client

OpenWrt

由于OpenWrt上没有对应的Go环境,所以没法用ngrok源码直接编译OpenWrt的客户端。但是dosgo大神写了一个C语言版本的ngrok-c,文档中也附带了编译方法。但是编译过程比较复杂,而且自己编译出来的二进制文件体积也不小,比较占空间,所以就在恩山上搜了一个民间高手编译好的装上了,顺带着LuCI界面放到服务器上:

wget https://www.shintaku.cc/files/ngrokc_ba56781152-1_ar71xx.ipk
wget https://www.shintaku.cc/files/luci-app-ngrokc_git-15.290.16504-8c2fd44-1_all.ipk

如果安装时遇到问题请确定路由器上是否已经安装了必要的库:

opkg install libstdcpp
opkg install libopenssl

启动

PC

先创建配置文件~/.ngrok并编辑,写入自己的域名和监听端口:

1
2
server_addr: "shintaku.cc:4443"
trust_host_root_certs: false

可以先用ngrok -h查看使用说明,然后指定二级域名和要映射的端口启动客户端:

ngrok -subdomain test 4000

就会出现Ngrok的连接状态:

ngrok (Ctrl+C to quit)

Tunnel Status online
Version 1.7/1.7
Forwarding http://test.shintaku.cc -> 127.0.0.1:4000
Forwarding https://test.shintaku.cc -> 127.0.0.1:4000
Web Interface 127.0.0.1:4040
# Conn 0
Avg Conn Time 0.00ms

然后再访问test.shintaku.cc就会发现和localhost:4000的内容是一样的,就说明Ngrok连接成功了:

也可以通过localhost:4040的Web页面查看连接状态:

Inbound Requests

如果要同时穿透多个端口也可以将它们都写在配置文件里:

1
2
3
4
5
6
7
8
9
10
server_addr: "shintaku.cc:4443"
trust_host_root_certs: false

tunnels:
test:
proto:
http: 4000
ssh:
proto:
tcp: 22

然后启动时加上要启动的tunnel名就可以了:

ngrok start test ssh

OpenWrt

路由器上装好了以后可以在服务-Ngrok Settings下设置:

OpenWrt

除了HTTP协议以外,也可映射TCP其他端口,例如ssh的22端口映射到远程的8022端口:

OpenWrt

这时ssh root@shintaku.cc -p 8022ssh root@192.168.1.1的效果是一样的,意味着即使在外面也可以访问没有公网地址的路由器了。更进一步,如果给路由器下连接的设备都分配了固定的局域网IP地址,将它们的端口映射到Ngrok服务器的端口,外网同样可以访问,这样就可以做很多事情了。

Read More +

DenyHosts防止ssh暴力登录

每次登录服务器都会提示:

There were xxxx failed login attempts since the last successful login.

就知道总有闲人在扫IP试密码。再看一下/var/log/secure就能知道这些失败登录的详情:

1
Aug 26 05:45:58 sgp1 sshd[4999]: Failed password for invalid user test from 128.199.92.158 port 38416 ssh2

所以我决定用DenyHosts屏蔽这些地址。DenyHosts是一个可以帮助阻止ssh攻击的脚本,它会分析/var/log/secure并记录多次失败登录的IP到/etc/hosts.deny中。

添加信任IP

编辑/etc/hosts.allow,将自己常用的IP加进去:

1
sshd: 202.113.*.*: allow

比如学校用的天津南开教育网,就把上面的IP段加进去,防止哪天自己手残输错几次密码IP被禁登不进去了。

安装配置DenyHosts

yum install denyhosts

安装完成后编辑/etc/denyhosts.conf文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
SECURE_LOG = /var/log/secure
HOSTS_DENY = /etc/hosts.deny
PURGE_DENY = 10w #禁止列表清理周期,不填就是永不清理
BLOCK_SERVICE = sshd
DENY_THRESHOLD_INVALID = 5 #非法用户失败登录次数
DENY_THRESHOLD_VALID = 5 #合法用户失败登录次数(不含root)
DENY_THRESHOLD_ROOT = 3 #root用户失败登录次数
DENY_THRESHOLD_RESTRICTED = 3 #限制用户失败登录次数
WORK_DIR = /var/lib/denyhosts
ETC_DIR = /etc
SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS = NO #是否报告来自允许列表的可疑登录
HOSTNAME_LOOKUP = NO #是否屏蔽被禁止IP对应的域名
LOCK_FILE = /var/lock/subsys/denyhosts

其中几个数字可以根据自己的需求修改,文件路径一般都不需要修改。另外还可以设置管理员邮箱ADMIN_EMAIL,默认是root@localhost,会把通知邮件发到/var/spool/mail下;也可以加上自己的其他邮箱。

启动服务

保存好配置文件后可以启动DenyHosts并加入到开机启动了:

systemctl start denyhosts
systemctl enable denyhosts

然后tail -f /etc/hosts.deny看一下禁用列表的动态,如果有:

1
2
3
4
5
6
7
8
9
10
# DenyHosts: Fri Aug 26 05:41:17 2016 | sshd: 87.106.142.246
sshd: 87.106.142.246
# DenyHosts: Fri Aug 26 05:41:17 2016 | sshd: 123.49.62.231
sshd: 123.49.62.231
# DenyHosts: Fri Aug 26 05:41:17 2016 | sshd: 45.32.20.165
sshd: 45.32.20.165
# DenyHosts: Fri Aug 26 05:41:17 2016 | sshd: 58.221.60.2
sshd: 58.221.60.2
# DenyHosts: Fri Aug 26 05:41:17 2016 | sshd: 118.71.224.139
sshd: 118.71.224.139

这样的内容出现就说明DenyHosts已经把之前记录里的可疑IP写进来了。我也把自己服务器上的hosts.deny放出来供大家(lā)考(hēi)。

Read More +

GFWlist+ShadowSocks实现路由器透明代理

前两个月OpenWrt一直使用ChinaDNS+ShadowSocks的方式按IP切换代理,但是由于长城宽带非常蛋疼代理时常上不去,导致平时可以正常访问的一些网站也无法访问,得不偿失。于是趁这周换了移动光纤,为了避免发生之前的情况,也把代理方式换成了按GFWlist得域名切换。

必要软件

首先是在OpenWrt下装上一堆必要软件:

  • ipset
  • iptables-mod-nat-extra
  • libopenssl
  • dnsmasq-full
  • shadowsocks-libev

其中前三个正常安装即可,dnsmasq-full需要先卸载预装的dnsmasq再安装。

shadowsocks-libev可以在sourceforge里找到。如果无法访问也可以下载我备份在服务器上的较老版本(注意软件所适配的架构):

wget https://www.shintaku.cc/files/shadowsocks-libev_2.4.8-3_ar71xx.ipk

下载完成后使用opkg install命令直接安装即可。

配置ShadowSocks

编辑/etc/shadowsocks.json文件:

1
2
3
4
5
6
7
8
{
"server": "",
"server_port": 8388,
"local_port": 1080,
"password": "",
"timeout": 300,
"method": "rc4-md5"
}

修改/etc/init.d/shadowsocks成如下(就是把关于ss-local的注释掉再把ss-redir的解注释):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/sh /etc/rc.common

START=95

SERVICE_USE_PID=1
SERVICE_WRITE_PID=1
SERVICE_DAEMONIZE=1

CONFIG=/etc/shadowsocks.json

start() {
#service_start /usr/bin/ss-local -c $CONFIG -b 0.0.0.0
service_start /usr/bin/ss-redir -c $CONFIG -b 0.0.0.0
#service_start /usr/bin/ss-tunnel -c $CONFIG -b 0.0.0.0 -l 5353 -L 8.8.8.8:53 -u
}

stop() {
#service_stop /usr/bin/ss-local
service_stop /usr/bin/ss-redir
#service_stop /usr/bin/ss-tunnel
}

之后启动ShadowSocks并设置开机自启:

/etc/init.d/shadowsocks start
/etc/init.d/shadowsocks enable

配置dnsmasq

新建目录/etc/dnsmasq.d,并在其中放入dnsmasq_list.conf文件,这个文件就是根据GFWlist生成的走代理的域名列表,生成方法已经有大神放在了GitHub上,可根据自己的情况进行修改。若是懒得生成,我在服务器上也会每日更新dnsmasq_list.conf,里面用的DNS是在这台服务器上搭的dnsmasq,ipset表叫做gfwlist

建议使用自己VPS上的DNS,具体就是在服务器装上dnsmasq,编辑/etc/dnsmasq.conf加入:

1
2
3
port=5353
server=8.8.8.8
server=8.8.4.4

保存后运行dnsmasq并设置开机启动就可以间接使用Google Public DNS了。

然后编辑路由器上的/etc/dnsmasq.conf,在全篇注释后面加一句:

1
conf-dir=/etc/dnsmasq.d

最后自定义防火墙规则(可在LuCI里直接添加):

1
2
ipset -N gfwlist iphash
iptables -t nat -A PREROUTING -p tcp -m set --match-set gfwlist dst -j REDIRECT --to-port 1080

重启dnsmasq就算完成了:

/etc/init.d/dnsmasq restart
Read More +

使用adb工具刷机

今天刷机小王子一加3终于给送来了,趁此机会总结一下之前用过的adb命令备查。

之前曾经用过Odin线刷、卡刷等方式,直到接触了Android Debug Bridge才发现命令行的强大。

首先通过Homebrew安装adb工具:

brew install android-platform-tools

OEM解锁

拿到一部新机一般OEM是上锁的。为了刷机我们需要对Bootloader进行解锁。这个过程会清除设备中的数据,所以需要提前进行备份。

首先进入关于手机连击版本号打开开发者模式,然后进入开发者模式打开OEM解锁,顺便将USB调试也打开。

这时用数据线将手机与电脑相连进行USB调试,在命令行里输入:

adb devices

如果设备列表中出现Android设备则说明连接成功,接着输入:

adb reboot bootloader

设备会重启到bootloader,此时使用命令:

fastboot oem unlock

在手机上进行确认后就解锁了bootloader。

刷入Recovery

设备自带的Recovery一般可能不如第三方的功能强大,这里推荐一个叫TWRP的Recovery,因为如果要刷Gapps的话可能需要用到它。首先到TeamWin下载对应设备的recovery包。

接着通过adb reboot bootloader进入bootloader,再输入:

fastboot flash recovery Recovery.img

就刷入新的recovery了,再通过fastboot reboot重启就可以了。

刷入ROM

先通过命令使设备重启为recovery模式:

adb reboot recovery

如果是刷入新系统建议先四清(System、Data、Cache、Dalvik Cache),如果是升级系统建议先三清(Data、Cache、Dalvik Cache),如果希望保留数据,双清(Cache、Dalvik Cache)就可以了。无论怎样最好都先备份数据。

首先将对应的ROM下载到电脑上。然后到手机上进入TWRP的Advanced,选择ADB Sideload。在电脑终端输入:

adb sideload ROM.zip

等待刷完就可以了。刷完后建议双清一下再重启。

刷入GAPPS(可选)

如果想要装上Google全家桶,在刷完ROM后先不要急于重启。先到OpenGAPPS下载对应版本的GAPPS到电脑上(注意Platform和Android版本),不同Variant区别在于:

Variant Description
aroma 图形化界面的super版,可以选择安装GAPPS
super 包含Google设备的所有Google Apps
stock 包含最新Nexus机型上预装的应用,并以GAPPS替换AOSP的同类应用
full 与stock版的内容相似,但不会替换AOSP应用
mini 包含完整的Google Play服务框架和主流应用
micro 包含完整的Google Play服务框架和少数应用(Gmail、Calender、Google Now)
nano 仅包含完整的Google Play服务框架
pico 仅包含最基础的Google Play服务框架

可以根据自己的需要进行下载。

最好在刷完ROM后立刻刷入GAPPS。依然进入ADB Sideload,并输入命令:

adb sideload open_gapps.zip

等待刷完后最好先双清一下再重启,否则可能会出现无限重启或停止工作的问题。

Root(可选)

root权限可以通过安装SuperSU的方式获取(CM13之类的系统可以在开发者选项里直接获取)。

先到chainfire下载最新版本的SuperSU,然后进入TWRP的ADB Sideload模式下直接通过adb sideload SuperSU.zip命令刷入即可。

安装apk(可选)

如果apk下载到了电脑上,无需拷贝到手机通过以下命令便可直接安装:

adb install APP.apk
Read More +

百度PHP实习生面试实录

人呐就都不知道,自己不可以预料,一个人的命运啊,当然要靠自我奋斗,但是也要考虑到历史的行程。我绝对不知道,我作为一个蒟蒻本科生怎么把我选到百度去了。所以HR同我讲话,说“人力资源部都决定了,你来当实习生。”我说另请高明吧,我实在也不是谦虚,我一个天津学生怎么到北京来了呢?但是,HR讲“大家已经研究决定了”。后来我念了两首诗,叫“苟利实习生死以,岂因远近避趋之”。所以我就作文以记之。

1番目

第一次是在6月17日(周五)下午,因为周六要考六级,所以正在复习周日要考的数理方程。两点钟左右面试官发来短信说三点开始电话面试,所以我花了一个小时的时间突击了一下我感觉会问到的算法、数据结构、操作系统、网络的知识。然而事实证明并没有什么卵用

3点过一点打来电话,听对面环境非常嘈杂,所以听起来非常吃力:

  • 首先先做一下自我介绍吧(大概是在翻简历)

    私は……

  • 有什么项目经历吗?

    (简要列举了一下做过的项目)

  • 我看了你的GitHub发现有不少项目,简要介绍几个吧~

    (随便挑几个说了)

  • 熟悉C++吧,说一说继承和多态吧~

    (因为面向对象用的不多,就随便说了说自己的理解)继承应该就是使用现有类的所有功能,在无需重新编写原来的类的情况下对这些功能进行扩展;多态就是允许将子类类型的指针赋值给父类类型的指针

  • C++最新的标准是多少?

    莫非是C++11?(后来查了一下发现都有C++17了)

  • 那你知道C++中的??(这两个字因为他那边太嘈杂了到现在都不知道说的是什么)吗?

    呃……(然后又问了几遍还是没听清,接下来就是蜜汁沉默)

  • (他察觉出这方面我不是很熟悉)不知道没关系,咱们再聊点别的。Java和C++的区别在哪?

    (随便扯一扯,大概是Java没指针、不支持多继承、对象只能由引用传递,C++没有包、接口、不能多个相同线程并发运行等等吧)

  • 那么来说一说重载和覆盖吧~

    (虽然不大清楚还是扯了一扯)重载一般是用于在一个类内实现若干重载的方法,这些方法的名称相同而参数形式不同;覆盖一般是用于子类在继承父类时,重写父类中的方法

  • PHP方面做过什么项目呢?

    (就把之前做过的PHP的东西详细说了说)

  • 有什么特别的功能吗?

    (就想了想项目里的亮点说了说)

  • 具体是怎么实现的?

    (一时没想起来就翻了一下GitHub跟他讲了讲)

  • 你在实验室中做些什么?

    (简要介绍了一下自己在实验室的工作)

  • 我这边问得差不多了,我先来介绍一下我们这边的情况吧(blabla一堆)……然后你有什么想问的吗?

    (就随便问了几个无关紧要的问题就结束了)

第一次电话面试大概用了一个小时的时间,由于时间太久远了肯定遗漏了很多问题没写出来,不过在最后比较有用的信息大概就是实习生面试大概有两到三轮技术面,一般没有HR面,面试题目基本看面试官个人喜好,基本觉得差不多就给通过了,差不多一周左右就会进入下一轮面试,不会要求太高。话虽如此,不过还是感觉自己面炸了,就没有往下准备~

2番目

第二次是在6月28日(周二)下午,因为第二天要检查FPGA大作业但那时还没有人做出来,所以在研究那个。大概差一刻6点的时候面试官打来电话问我什么时候方便电面,我说就现在吧早面试完早搞FPGA,于是他准备了5分钟再次打来电话开始面试:

  • 首先先做一下自我介绍吧(老套路)

    私は……

  • 我看你简历上写熟悉Linux,列举几条你常用的Linux命令吧~

    wcdiffgrepfind等等吧

  • 看起来都是些查找统计的命令,要是对比两个目录下的文件名用什么命令?

    应该也是用diff吧,再加个参数,具体什么参数不清楚~

  • 那你回来再查查吧;如果让你杀死某个进程要怎么做?

    先用ps找到进程号然后kill掉吧~

  • 要是只用一条命令怎么写呢?(这时对面响起了敲键盘的声音)

    要用到管道吧,先把PIDcut出来(当时口误说成cat了),具体怎么写没想出来(对方还提示了半天)

  • awk你了解吗?

    用的不是很多,不太熟悉~

  • 问点PHP吧,你知道include()require()的区别在哪吗?

    (这个之前看过,但是一时想不起来,就扯了扯require()require_once()的区别,答案应该是遇到错误时include()会产生一个警告,而require()导致一个致命错误)

  • PHP怎么获取用户ip地址?

    应该是$_SERVER[]吧~

  • 那么怎么获取网页内容?

    这个没用过,真不知道(其实应该是file_get_contents($url)

  • 介绍一下简历上的XX项目吧,都有什么功能?

    (介绍一下功能)

  • 用户登录是怎么实现的?

    用了个全局变量表示登录状态(当时写的比较SB,怎么会用这种方法呢)~

  • 那样的话关闭浏览器再打开状态就丢了吧~一般要用SESSION吧,SESSION你知道吗?

    (这时我才恍然大悟刚才直接说这个不就好了吗)用过用过,在YY项目里登录我是用SESSION实现的。

  • 那你再介绍一下YY项目的工程吧~

    (blabla一大堆)

  • 那么数据库中ZZ的数据是怎么存的呢?

    (balbla介绍了一下数据库的结构)

  • 怎么按条件查询呢?

    (blabla介绍了一下查询方法)

  • 我看你还写过Java,做过Java的什么项目吗?

    并没有,只是写了点Application,Android的算吗?

  • 算吧,说说看~

    (blabbla介绍了一下功能)

  • 具体是怎么实现的呢?

    调用了为了CC而使用的GG接口~

  • 哦,那和Windows下的JJ挺像的。你还了解一点Python是吧?

    一般当脚本用的,处理数据用。

  • 我们这边还会用到go来开发平台,go你知道吗?

    golang啊,听说过。

  • 对,要是来我们这边也会用到。你那边还有一些其他问题要问吗?

    暂时想不到了,第一轮时基本问过了(因为我赶着做大作业啊)~

然后寒暄了一阵就挂掉了电话,总共用时大约半小时。虽然没有抱太大希望,但是感觉百度的面试官还是非常Nice的,但是这样的面试真心无从准备,但是一定要熟悉自己简历上的内容(面试问题基本围绕简历展开)和投递职位的工作内容,其他的就完全靠姿势水平啊~

Read More +

OpenWrt上的ssh免密登录

一般在用OpenSSH服务器的系统上进行ssh登录时,我们只需要在本地生成密钥(yuè)对,将私钥(yuè)留在本地,将公钥(yuè)上传到目标服务器上就可以了,具体如下:

ssh-keygen
cat ~/.ssh/id_rsa.pub | ssh remote_username@remote_host 'cat >> .ssh/authorized_keys'

然而OpenWrt上的ssh服务器却用的Dropbear,它是一种在较低内存和处理器资源的嵌入式系统中替代OpenSSH的软件,因此使用起来用诸多的不同。

免密登录到OpenWrt

如果本地是用ssh-keygen生成的密钥对,那么只需要将公钥上传到路由器的/etc/dropbear/authorized_keys中就行了:

cat ~/.ssh/id_rsa.pub | ssh root@192.168.1.1 'cat >> /etc/dropbear/authorized_keys'

从OpenWrt登录到其他机器

首先登入到OpenWrt。但想从OpenWrt免密登录其他机器,也要先生成密钥对并将公钥上传。由于无法使用ssh-keygen,我们可以直接用dropbearkey生成:

dropbearkey -t rsa -f ~/.ssh/id_rsa
Generating key, this may take a while…
Public key portion is:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCn02fMyD2T1ECmDZso8EG1m/4eo5LJtNlbqCMu0SkABsOUvmTHozrPzoJ10SlcAhjnc84S//VGEAbNJxUTaYn0M7f7M8Q4NBSyPF9DMcNAWKM01OSll8BWLQafZeZneW+UOwO6h1LOd6UEaLS8lhKQUD05+dSzKhPHimZudlhkV2bO7KOkiFh3P4K1GakHBuXitB1V9QH144BKKlSqNXy7TZcJf5/oRkB76ZmdSDDMQtvfCHF1BZwggStgBsu9K6nAl8lz9MOVHCYs9AkEIurldrHLUKvoGJ4QA5yc3bEMQaMH7vu3G5YMysIY4w5+aVuZh5Wg4THoh6yXPfGUc7Mh root@OpenWrt
Fingerprint: md5 2d:8f:e9:e7:31:75:f0:f4:ba:b8:54:4c:2f:43:9b:33

这样就将私钥生成到~/.ssh/id_rsa了,并将公钥打印到了屏幕上。建议将公钥也保存下来,以便以后使用:

echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCn02fMyD2T1ECmDZso8EG1m/4eo5LJtNlbqCMu0SkABsOUvmTHozrPzoJ10SlcAhjnc84S//VGEAbNJxUTaYn0M7f7M8Q4NBSyPF9DMcNAWKM01OSll8BWLQafZeZneW+UOwO6h1LOd6UEaLS8lhKQUD05+dSzKhPHimZudlhkV2bO7KOkiFh3P4K1GakHBuXitB1V9QH144BKKlSqNXy7TZcJf5/oRkB76ZmdSDDMQtvfCHF1BZwggStgBsu9K6nAl8lz9MOVHCYs9AkEIurldrHLUKvoGJ4QA5yc3bEMQaMH7vu3G5YMysIY4w5+aVuZh5Wg4THoh6yXPfGUc7Mh root@OpenWrt" > ~/.ssh/id_rsa.pub

然后就和原来一样,将公钥上传到目标服务器就可以了:

cat ~/.ssh/id_rsa.pub | ssh remote_username@remote_host 'cat >> .ssh/authorized_keys'

但是在登录的时候要注意,使用ssh命令需要加-i参数指定所用的私钥:

ssh -i ~/.ssh/id_rsa remote_username@remote_host

记得使用scp等类似命令也要这样。

Read More +