Blog - wingsico

前言

之前那一觉睡的有点久啊嘿嘿,废话少说,直接开始进入正题吧,实现Linux的定时服务。

准备工作

自己的电脑是Mac OS,命令跟linux差不多吧,但是定时任务也不应该在自己的电脑上跑吧,因为自己的电脑总会关的,服务也会停止的。所以我选择了我的博客所在的服务器,这个是linux centos系统。这个是我在腾讯云花一元/月领的(现在这个活动已经结束啦),ok,自动签到js脚本和服务器都有了,可以开始我们的任务了。

start!

首先,服务器上还没有我们的脚本,我们需要把我们的脚本上传到服务器里,怎么上传呢? 在mac os里(may linux里也有),进入我们脚本所在目录:

➜ ~ cd ~/my-github/nodejs/util
➜ ~ scp checkin.js root@wingsico.org:/home/checkin.js
password:
ok

这样就上传到我们服务器的/home目录下,并将文件命名为checkin.js 可以通过ssh进入服务器查看一下,很好,/home目录下已经有我们的脚本文件checkin.js了,先尝试运行一波:

[root@VM_48_13_centos ~/home]# node checkin.js
[root@VM_48_13_centos ~]# cd /var/spool/mail/
[root@VM_48_13_centos mail]# nano root
// 翻到最后一行
OK {“msg”:”\u83b7\u5f97\u4e86 96 MB\u6d41\u91cf.”,”ret”:1}

签到成功了,ok,那么我们就开始写定时服务。

定时服务

在linux中我们使用crontab这个命令来管理定时任务,我们可以使用crontab –help(其实是靠输入错误来弹出相关提示…)来查看相关命令:

usage: crontab [-u user] file
crontab [-u user] [ -e | -l | -r ]
(default operation is replace, per 1003.2)
-e (edit user’s crontab)
-l (list user’s crontab)
-r (delete user’s crontab)
-i (prompt before deleting user’s crontab)
-s (selinux context)

为了更好的运行脚本,我们写一个shell脚本来运行js脚本:

#!/bin/sh
/root/.nvm/versions/node/v8.7.0/bin/node /home/checkin.js

发现了吗?我们这里没有直接用node来运行js脚本,因为shell脚本运行的环境不同,不能直接通过node来运行js脚本,我们使用which node来找到node的运行的源文件,保存在统一目录下,命名为checkin.sh,接下来我们在定时任务里就可以直接运行这个脚本就好了,现在来编辑定时任务了,输入crontab -e,添加

10 09 * * * sudo bash /home/checkin.sh &

前面的参数的含义就是 每天的9点10分,这个命令就是在每天9点10分运行一次checkin.sh脚本,记得加sudo,不然会在日志中提示权限不够。好了,之后输入:

[root@VM_48_13_centos ~]# /sbin/service crond start

开启定时服务~之后如果修改crontab的话使用

[root@VM_48_13_centos ~]# /sbin/service crond restart

即可~

起因

曾在大一的时候就听田大佬写了一个每日自动签到的脚本,觉得很牛逼,不过现在看起来确实和当初田大佬说的那样简单>,<,话不多说,直接开始吧。

准备工作

首先这个签到是我学校的一个工作室的内部网站的签到。一开始认为只需要登录了就算签到了(大一不了解的时候),现在知道了,其浏览器上的流程大概是: 打开登录页面 ——> 输入账号密码 ——> 点击登录 ——> 登录成功&自动完成签到; 其内部实现为: 输入网址 ——> 发送get请求 ——> 拿到返回的html并展示 ——> 输入账号密码 ——> 将账号密码放在请求体内通过post请求发送到对应的登录api ——> 拿到对应api所返回的数据(这里我们只需要token) ——> 对签到的api发送一个post请求,将token放入请求头中发送 ——> 签到成功. 那么如何实现以上操作呢?

实现

首先,打开us.ncuos.com(我们内部的网站), f12打开chrome debugger tools,点击network,钩上presever log,然后输入账号密码,点击登录,成功之后右边就会出现一堆请求,我们找到Name为login的包,找到这几项 这里标清楚了请求的url,method和请求体的类型,根据这三个我们可以很简单的写一个模拟登录来拿到对应的token:

var request = require('request') // 引入request包

var contents = {
  username: '613*****',
  password: '******',
  remember_me: false
} // 请求体,目前为一个对象

var options = {
  url: 'http://us.ncuos.com/api/user/login', // 请求的url
  method: 'POST', // 请求的方式 post
  headers: { // 设置请求头
    'Content-Type': 'application/json; charset=utf-8'
  },
  body: JSON.stringify(contents) // 对象JSON化
}

// 发送一个请求,
request(options, (error, response, body) => {
  if (!error && response.statusCode == 200) {
    var token = response.headers.authorization // 响应头里存储着token
    console.log(token)
  }
})

ok,是不是很简单呢,这样我们就拿到了token,就可以为所欲为了啊嘎嘎,比如爬个帖子内容啥的!哦不,回归正题,签到签到,我们再次回到浏览器,我们登录之后还请求了一些别的数据,比如Name为checkin的就是我们要找的签到的api, 由于这个接口是没有请求体的,所以我们不需要类似上面的contents了,只需要在登录之后再发送一个post请求,设置好请求头就可以了,由于代码比较短,就直接放在登录成功后的if语句内:

request(options, (error, response, body) => {
  if (!error && response.statusCode == 200) {
    var token = response.headers.authorization // 响应头里存储着token
    var params = {
      "url": 'http://us.ncuos.com/api/checkin', // 请求url
      "method": 'POST', // 请求方式
      "headers": { // 请求头
        "Content-Type": "Application/json", // 请求体格式
        "Authorization": token // auth token授权
      }
    }
    request(params, (error, response, body) => {
      if (!error && response.statusCode == 200) {
        console.log(body) // 打印出响应体
      } else {
        console.log(error)
      }
    })
  }
})

写好了之后,保存为checkin.js, 执行node checkin.js,发现打印出来的是null,什么情况,为了查看原因,我们将签到请求做出一些修改:

request(params, (error, response, body) => {
  console.log(response.statusCode, response.statusMessage)
  if (!error && response.statusCode == 200) {
    console.log(body) // 打印出响应体
  } else {
    console.log(error)
  }
})

发现打印了 400,forbidden,null,再打印了一下整个response,发现在error里有更加详细的一个报错:

body: ‘{“error”: “InvalidData”, “message”: “invalid json content”, “status”: 400}’ } ‘{“error”: “InvalidData”, “message”: “invalid json content”, “status”: 400}’

很容易看出,error为非法json格式内容。wtf?啥情况,我这个根本不需要请求体啊,为什么还来个这个错误呢,于是走上了漫漫排查之路。

debugger

我首先先尝试了一下console.log(params),发现headers里的Authorization少了引号: 难道是这个的原因吗?然后我尝试了各种方法还是不能将引号加上,不过JSON.stringify(params) 之后是有引号的,所以觉得不是这个问题。苦思冥想无果之后,求助了一下学长,把情况说清楚之后,学长给出了一个尝试建议: 把headers里面的’Content-Type’去掉试试,去掉之后,我靠真的就成功了。之后探其原因是设置请求头中多余地规定了请求体的格式,但是你并没有也不需要发送请求体(对于这个api),但设置了这个请求头之后就强制的要求了你的格式,所以导致上面的报错信息,非法的content。为了验证这个想法,我把Content-type重新加上,写了一个json格式的请求体,里面数据随便填,果然也成功了!至此,我们的这个签到脚本就完成了。最终代码如下:

var http = require('http')
var request = require('request')

var contents = {
  username: 'username',
  password: 'password',
  remember_me: false
}

var options = {
  url: 'http://us.ncuos.com/api/user/login',
  method: 'POST',
  headers: {
    'Content-Type': 'application/json; charset=utf-8'
  },
  body: JSON.stringify(contents)
}


request(options, (error, response, body) => {
  if (!error && response.statusCode == 200) {
    var token = response.headers.authorization
    var params = {
      "url": 'http://us.ncuos.com/api/checkin',
      "method": 'POST',
      "headers": {
        "Authorization": token
      }
    }
    request(params, (error, response, body) => {
      if (!error && response.statusCode == 200) {
        console.log(body)
      } else {
        console.log(error)
      }
    })
  }
});

但是这样每天我们还是需要去自己执行一下这个脚本,还是不如自己手动去登录一下签到呢,所以等下我们就要实现的是 Linux服务器定时任务,可以每日定时执行这个脚本,就可以每日自动签到了,这个留到下一篇博客讲吧~先去睡觉~

最近不在机房,不能享受自动翻墙的”快感”了,呼幸好手里还有一个ss账号,那直接给ubuntu来一套科学上网的正确姿势吧~

科学上网

科学上网一词我是听别人说+看到一本书《程序员的自我修养》里面的一章节,里面介绍了什么是墙,如何翻墙,以及vpn相关概念。根据我所了解的来说,科学上网的方式共有两种——VPN & Shadowsocks。那么这两个有什么区别呢?

VPN


在公用网络上建立专用网络,进行加密通讯。原理是在一个国外网络无阻的机器上与本地机器通信。

优点是方便设置,网络速度稳定。

缺点是稳定的服务价格不便宜,且本地流量全部走的是代理。

一看到连本地流量走的都是代理,震惊了,本来价格都是按照流量来算的,如果连国内网站都走代理的话,那不是亏成翔。还好目前有解决办法。

配合VPN实现国内外分流访问


“分流”,这个词不知道说的准不准确,意思就是实现对不需要翻墙的网站直接连接,需要翻墙的网站走VPN代理。这样国内的网站访问不受影响,又能正常访问国外站点。

实现方式就是修改系统的路由表,网络上有这样的开源项目,专门收集国内被“墙”的网站。利用这些数据,让vpn客户端在进行连接的时候自动执行.

通过这些路由脚本, 可以让用户在使用vpn作为默认网络网关的时候, 不使用vpn进行对中国国内ip的访问, 从而减轻vpn的负担, 和增加访问国内网站的速度.

关于各个系统实现的方式我就不在这里赘述,详情请看这里 科学上网

Shadowsocks!


这是另一种科学上网的姿势,我选择他!因为vpn的缺点他都没有~这也是我接下来要讲的,如标题一般,那么我们就以shadowsocks开始吧。

Start!

首先,我们需要下载安装Shadowsocks,在linux Ubuntu16.04中,我们使用pip安装。

  1. 安装pip

    apt-get install python-pip

  2. 安装shadowsocks

    pip install shadowsocks

  3. 使用 这里介绍两种使用方法,但推荐第二种方法。 1.无配置文件,一行命令搞定

    sslocal -s server_ip -p server_port -l 1080 -k password -t 600 -m aes-256-cfb

    server_ip 请替换成对应的服务ip, server_port 替换成对应的服务端口号, -l是本地端口(默认1080), -k后面填写密码(password)需要加双引号(“”) 如密码是123456,则应写成 -k "123456" , -t是默认超时时间, -m是加密方法,这个会由服务端给出,默认值为aes-256-cfb。 可以简单的写为:

    sslocal -s ip -p port -k “password”

    只使用-s -p -k这三个参数,其他的使用默认值(注意要与服务端匹配才能省略) 缺点:每次输入命令都要手动填写相关信息,比较麻烦。所以我推荐第二种。 2.添加配置文件,更加简短的命令。

    sslocal -c path/to/ss.json

    怎么样,是不是更加简短了呢?这里,我们将使用到一个配置文件,这个是由我们自己来创建,不知道放在哪里好,我自己就放在/home目录下。 方法:选择一个目录,创建一个json格式的文件,名字自己定义,打开后,如下填入ss的相关信息.

    {

    "server":"server_ip",
    "server\_port": server\_port,
    "local_address":"127.0.0.1",
    "local_port":1080,
    "password":"password",
    "timeout":300,
    "method":"aes-256-cfb",
    "fast_open":false

    }

    注意:上面打了双引号的在实际使用的时候也需要双引号。保存之后,在命令行里使用上面那条命令就可以启动ss了。

这样就行了吗?还不行呢,使用Shadowsocks我们还需要设置一下浏览器端的代理设置。这里仅介绍chrome浏览器下的方法。

SwitchyOmega

这个是Chrome的一个插件,非常好用。之前一直在搜索如何下载 SwitchyOmega ,我靠竟然还有叫人去谷歌商店下载的。。我还没翻墙呢怎么去谷歌商店,坑爹呢这是。想想这么好的东西可能开源了吧,于是就到github上去找找,嘿;-)果然被我找到了,放一下下载地址~ https://github.com/FelisCatus/SwitchyOmega/releases/ 下载好了之后打开谷歌浏览器,输入chrome://extensions,将刚刚下载好的拖入就可以安装了。那么安装好了如何使用呢?

使用SwitchyOmega


废话少说,直接上操作:

  1. 新建情景模式
  2. 填写名称(自定义),选择第一个代理服务器,点击创建
  3. 进入刚创建的情景模式,将代理协议选择至SOCKS5,代理服务器处填写:127.0.0.1,代理端口填写1080
  4. 保存,并在浏览器右上角选择到刚刚创建的情景模式。

OK,这时候你就会发现谷歌能上了,youtube能看了,世界突然变美好了(滑稽)