jenkins使用开始踩坑(1)

一.前戏

话说上一篇文章安装完 JDK 和 jenkins 之后 , 在使用的时候遇到了很多问题,现在一一和大家分享一下

二.问题1

1.目的:因为第一次使用jenkins,不太会用,给自己的一个小目标就是执行一个python的脚本

2.过程

前期也没有配置jenkins 直接打开就开始新建任务(过程省略,啥都没配置,只是执行了这样一个命令 python *.py),刚开始学或者已经用过的同学应该能看懂我说的啥。

好,继续,接下来就是【立即构建】,问题来了,执行这么简单的一个脚本既然给我报错。没错了,报错信息意思找不到selenium包

ft1.1: ImportError: Failed to import test module: LoginTc
Traceback (most recent call last):
  File "C:Python36libunittestloader.py", line 428, in _find_test_path
    module = self._get_module_from_name(name)
  File "C:Python36libunittestloader.py", line 369, in _get_module_from_name
    __import__(name)
  File "D:Petrochina_Retail_Test_Projectretailtest_caseLoginTc.py", line 11, in <module>
    from retail.test_case.models.myunit import MyunitTest
  File "D:Petrochina_Retail_Test_Projectretailtest_casemodelsmyunit.py", line 7, in <module>
    from retail.test_case.models.driver import WDriver
  File "D:Petrochina_Retail_Test_Projectretailtest_casemodelsdriver.py", line 7, in <module>
 from selenium import webdriver
ModuleNotFoundError: No module named 'selenium'

  
3.解决:再IDE中运行这个脚本没有问题,在cmd下运行也没有问题,很伤, 查看各种环境变量 发现没有问题,于是卸载jenkins重新安装试试,发现还是不行,经过几个小时的折腾,发现确实在python安装目录的C:Python36Libsite-packages 下面没有selenium包。之前可能被cmd和IDE给忽悠了,我去找了一下IDE中在哪里引入seleniium包,关键来了,看图:

未分类

你现在看到的目录是我改过后的,原来的目录是:c:usersv-xugappdataroamingpythonpython36site-packages 很奇怪为什么会在这,原来是安装的时候我自己设置到了这个目录,导致jenkins在找selenium包找不到,于是把selenium 复制到python的目录里面,再次构建

三.问题2

1.过程:发现新问题了,脚本是执行了而且jenkins控制台也没有报错,但是我的脚本里面有执行打开浏览器的操作,可以实际我并没有看见浏览器被打开,就执行结束了

2.解决:伤心呀!百度。找到这样一篇文章 Jenkins调度Selenium脚本不打开浏览器解决办法

于是按照上面步骤开始操作,问题来了 我发现我运行不了java命令,提示信息是说 我的JDK是11 而jenkins 需要运行JDK8 于是卸载JDK 重新安装8的版本。一步一步,都做完之后惊喜的发现真的解决了,很开心! 这篇文章写的很乱,因为好多东西我没有记录,没法看到一些错误信息,但是大体的问题就是这样,希望遇到一样的情况的同学能帮到你一点点小忙。

Jenkins调度Selenium脚本不打开浏览器解决办法

The web browser doesn’t show while run selenium test via jenkins
原因:因为jenkins是用windows installer 安装成 windows的服务了,那么jenkins是一个后台服务,所以跑selenium cases 的时候不显示浏览器
  
解决办法:

Step 1. Control Panel(控制面板) -> Administrative Tools(管理工具) -> Services(服务)
找到Jenkins,右键菜单,执行stop; 右键菜单 “属性” start type 选择“Disabled” 点击 应用,点击确定。(这一步目的:让jenkins不在以windows 服务的方式在后台运行)
  
Step2. 通过命令行启动Jenkins
java -jar “D:Program Files (x86)Jenkinsjenkins.war”
当然,大家也可以做个bat文件,以后每次启动jenkins,双击运行这个bat文件就OK了,bat文件内容如下:
  

echo "Jenkins CI automation testting"
java -jar "D:Program Files (x86)Jenkinsjenkins.war"
pause

Step3. 重新创建Jenkins的Job,重新配置,在执行测试
问题解决了。
  
注意问题:

(1)通过这种方式启动jenkins,之前以windows service 启动jenkins的数据都丢失了,需要重新创建job。
(2)之前以windows service 启动jenkins中安装的插件也没有了,需要重新安装所需插件。

Jenkins和Git稀疏结账

您可以使用Git的稀疏结账功能。 请注意,Git仍将整个存储库克隆到本地磁盘。 然而,这并不是太糟糕,因为它是压缩的。

1.在Jenkins中创建一个新作业,在源代码管理部分设置Git存储库。
2.建立项目。 这会将整个存储库克隆到本地磁盘。
3.打开项目的工作区文件夹,删除除.git文件夹之外的所有内容。
4.打开项目工作区文件夹的Git shell。 启用稀疏检查:

git config core.sparsecheckout true

5.更新工作树:

git read-tree -mu HEAD

6.在.git / info文件夹中创建sparse-checkout文件。 添加要签出到该文件的子文件夹的路径,如下所示(注意尾部斜杠):

folder/to/include/

7.再次构建项目。 这次只有一个子文件夹应出现在工作区文件夹中。

curl 调用jenkins的api

jenkins提供了rest api,通过调用接口,可以执行一些job的操作,如构建job ,新建job,启用禁用等操作骑车

其次curl是什么?

cURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行。它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具。 cURL还包含了用于程序开发的libcurl。

cURL支持的通信协议有FTP、FTPS、HTTP、HTTPS、TFTP、SFTP、Gopher、SCP、Telnet、DICT、FILE、LDAP、LDAPS、IMAP、POP3、SMTP和RTSP。

curl还支持SSL认证、HTTP POST、HTTP PUT、FTP上传, HTTP form based upload、proxies、HTTP/2、cookies、用户名+密码认证(Basic, Plain, Digest, CRAM-MD5, NTLM, Negotiate and Kerberos)、file transfer resume、proxy tunneling。

可以看出curl支持http协议,所以调用jenkins的rest api是没有问题的。

接下来示例演示操作cur 对jenkins的job的启用和禁用及构建,示例中用到的jenkins url为:http://localhost:8080/jenkins/,job名称为:login,jenkins管理员账号:root, 密码:root

启用job login

curl --user root:root --data enable http://localhost:8080/jenkins/job/login/enable

禁用job login

curl --user root:root --data disable http://localhost:8080/jenkins/job/login/disable

构建job login

curl --user root:root --data build http://localhost:8080/jenkins/job/login/build

命令中–user 表示jenkins账号密码认证

执行结果如下(如果在windows下,是没有办法直接在cmd下执行curl命令,可以下git的客户端,在git bash中执行命令)

Administrator@OXPLAJ8T7PEPCDB MINGW64 ~
$ curl --user root:root  --data disable  http://localhost:8080/jenkins/job/login/disable
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100     7    0     0  100     7      0      7  0:00:01 --:--:--  0:00:01    56

Administrator@OXPLAJ8T7PEPCDB MINGW64 ~
$ curl --user root:root  --data enable  http://localhost:8080/jenkins/job/login/enable
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100     6    0     0  100     6      0      6  0:00:01 --:--:--  0:00:01    42

Administrator@OXPLAJ8T7PEPCDB MINGW64 ~
$ curl --user root:root  --data build http://localhost:8080/jenkins/job/login/build
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100     5    0     0  100     5      0      5  0:00:01 --:--:--  0:00:01    35

Administrator@OXPLAJ8T7PEPCDB MINGW64 ~
$

执行后在jenkins页面查看,可以看到禁用、停用、构建job

Jenkins pipeline 并行执行任务流

笔者在 https://www.cnblogs.com/sparkdev/p/7617765.html 一文中介绍了如何在声明式 pipeline 中执行并行的任务。前一段时间,Jenkins 发布了 1.3 版的声明式 pipeline(declarative pipeline),这个版本继续增强了并行执行任务的能力:并行执行的任务可以是个任务流。官方称这一功能为 “sequential stages”,本文将解释 “sequential stages”,并通过 demo 演示其用法。

之前的任务并行方式

就是笔者在 https://www.cnblogs.com/sparkdev/p/7617765.html 一文中介绍的方式,我们在一个 stage 中设置多个子 stage 并行执行:

stages {
    stage('Stage1') {
        ...
    }
    stage('并行执行的 Stage') {
        parallel {
            stage('Stage2.1') {
                agent { label "test1" }
                steps {
                    echo "在 agent test1 上执行的并行任务 1."
                }
            }
            stage('Stage2.2') {
                agent { label "test2" }
                steps {
                    echo "在 agent test2 上执行的并行任务 2."
                }
            }
        }
    }
    stage('Stage3') {
        ...
    }
}

上面代码中任务的执行过程如下图所示:

未分类

任务 2.1 和任务 2.2 并行执行。

并行执行任务流

过去并行执行的任务都是单个的,但实际情况中我们还需要任务流级别的并行能力,如下图所示:

未分类

上图中显示有两条任务流在并行的执行,我们可以通过下面的代码来实现:

pipeline {
    agent none

    stages {
        stage('Stage1') {
            agent { label "master" }
            steps {
                timestamps {
                    echo '这是第一个被执行的 stage.'
                    sleep 5
                }
            }
        }
        stage("build, deploy and test on Windows and Linux") {
            parallel {
                stage("windows") {
                    agent {
                        label "master"
                    }
                    stages {
                        stage("build") {
                            steps {
                                timestamps {
                                    echo "build on windows."
                                }
                            }
                        }
                        stage("deploy") {
                            steps {
                                timestamps {
                                    echo "deploy on windows."
                                }
                            }
                        }
                        stage("test") {
                            steps {
                                timestamps {
                                    echo "test on windows."
                                    sleep 5
                                }
                            }
                        }
                    }
                }

                stage("linux") {
                    agent {
                        label "worker1"
                    }
                    stages {
                        stage("build") {
                            steps {
                                timestamps {
                                    echo "build on linux."
                                }
                            }
                        }
                        stage("deploy") {
                             steps {
                                 timestamps {
                                     echo "deploy on linux."
                                 }
                            }
                        }
                        stage("test") {
                            steps {
                                timestamps {
                                    echo "test on linux."
                                    sleep 5
                                }
                            }
                        }
                    }
                }
            }
        }
        stage('Stage3') {
            agent { label "worker1" }
            steps {
                timestamps {
                    echo '这是最后一个被执行的 stage.'
                }
            }
        }
    }
}

为了显示任务的执行时间,笔者使用了 timestamper 插件。下图显示了笔者精简后的运行日志:

未分类

红框中的内容说明我们的两个任务流是完全并行执行的。这就是 1.3 版的声明式 pipeline 中增加的 “sequential stages” 功能。

总结

如今 jenkins 对声明式 pipeline 中并行任务的执行支持的非常给力(虽然经历了一个稍显漫长的过程)。笔者在 2017 年初调研时发现声明式 pipeline 无法支持并行的任务,后来开始支持比较初级的并行任务,笔者在 https://www.cnblogs.com/sparkdev/p/7617765.html 一文中进行了介绍。到今年(2018) 7 月份声明式 pipeline 发布了版本 1.3,这个版本中开始支持本文介绍的任务流级别的并行。至此笔者认为 jenkins 声明式 pipeline 中任务的并行执行功能已经比较完善了。

wget

Linux系统中的wget是一个下载文件的工具,它用在命令行下。对于Linux用户是必不可少的工具,我们经常要下载一些软件或从远程服务器恢复备份到本地服务器。wget支持HTTP,HTTPS和FTP协议,可以使用HTTP代理。所谓的自动下载是指,wget可以在用户退出系统的之后在后台执行。这意味这你可以登录系统,启动一个wget下载任务,然后退出系统,wget将在后台执行直到任务完成,相对于其它大部分浏览器在下载大量数据时需要用户一直的参与,这省去了极大的麻烦。

wget 可以跟踪HTML页面上的链接依次下载来创建远程服务器的本地版本,完全重建原始站点的目录结构。这又常被称作”递归下载”。在递归下载的时候,wget 遵循Robot Exclusion标准(/robots.txt). wget可以在下载的同时,将链接转换成指向本地文件,以方便离线浏览。

wget 非常稳定,它在带宽很窄的情况下和不稳定网络中有很强的适应性.如果是由于网络的原因下载失败,wget会不断的尝试,直到整个文件下载完毕。如果是服务器打断下载过程,它会再次联到服务器上从停止的地方继续下载。这对从那些限定了链接时间的服务器上下载大文件非常有用。

1.命令格式

wget [参数] [URL地址]

2.命令功能

用于从网络上下载资源,没有指定目录,下载资源回默认为当前目录。wget虽然功能强大,但是使用起来还是比较简单:

1)支持断点下传功能;这一点,也是网络蚂蚁和FlashGet当年最大的卖点,现在,Wget也可以使用此功能,那些网络不是太好的用户可以放心了;

2)同时支持FTP和HTTP下载方式;尽管现在大部分软件可以使用HTTP方式下载,但是,有些时候,仍然需要使用FTP方式下载软件;

3)支持代理服务器;对安全强度很高的系统而言,一般不会将自己的系统直接暴露在互联网上,所以,支持代理是下载软件必须有的功能;

4)设置方便简单;可能,习惯图形界面的用户已经不是太习惯命令行了,但是,命令行在设置上其实有更多的优点,最少,鼠标可以少点很多次,也不要担心是否错点鼠标;

5)程序小,完全免费;程序小可以考虑不计,因为现在的硬盘实在太大了;完全免费就不得不考虑了,即使网络上有很多所谓的免费软件,但是,这些软件的广告却不是我们喜欢的。

3.命令参数

启动参数:

-V, –version 显示wget的版本后退出
-h, –help 打印语法帮助
-b, –background 启动后转入后台执行
-e, –execute=COMMAND 执行`.wgetrc’格式的命令,wgetrc格式参见/etc/wgetrc或~/.wgetrc

记录和输入文件参数:

-o, –output-file=FILE 把记录写到FILE文件中
-a, –append-output=FILE 把记录追加到FILE文件中
-d, –debug 打印调试输出
-q, –quiet 安静模式(没有输出)
-v, –verbose 冗长模式(这是缺省设置)
-nv, –non-verbose 关掉冗长模式,但不是安静模式
-i, –input-file=FILE 下载在FILE文件中出现的URLs
-F, –force-html 把输入文件当作HTML格式文件对待
-B, –base=URL 将URL作为在-F -i参数指定的文件中出现的相对链接的前缀
–sslcertfile=FILE 可选客户端证书
–sslcertkey=KEYFILE 可选客户端证书的KEYFILE
–egd-file=FILE 指定EGD socket的文件名

下载参数:

–bind-address=ADDRESS 指定本地使用地址(主机名或IP,当本地有多个IP或名字时使用)
-t, –tries=NUMBER 设定最大尝试链接次数(0 表示无限制).
-O –output-document=FILE 把文档写到FILE文件中
-nc, –no-clobber 不要覆盖存在的文件或使用.#前缀
-c, –continue 接着下载没下载完的文件
–progress=TYPE 设定进程条标记
-N, –timestamping 不要重新下载文件除非比本地文件新
-S, –server-response 打印服务器的回应
–spider 不下载任何东西
-T, –timeout=SECONDS 设定响应超时的秒数
-w, –wait=SECONDS 两次尝试之间间隔SECONDS秒
–waitretry=SECONDS 在重新链接之间等待1…SECONDS秒
–random-wait 在下载之间等待0…2*WAIT秒
-Y, –proxy=on/off 打开或关闭代理
-Q, –quota=NUMBER 设置下载的容量限制
–limit-rate=RATE 限定下载输率

目录参数:

-nd –no-directories 不创建目录
-x, –force-directories 强制创建目录
-nH, –no-host-directories 不创建主机目录
-P, –directory-prefix=PREFIX 将文件保存到目录 PREFIX/…
–cut-dirs=NUMBER 忽略 NUMBER层远程目录

HTTP 选项参数:

–http-user=USER 设定HTTP用户名为 USER.
–http-passwd=PASS 设定http密码为 PASS
-C, –cache=on/off 允许/不允许服务器端的数据缓存 (一般情况下允许)
-E, –html-extension 将所有text/html文档以.html扩展名保存
–ignore-length 忽略 `Content-Length’头域
–header=STRING 在headers中插入字符串 STRING
–proxy-user=USER 设定代理的用户名为 USER
–proxy-passwd=PASS 设定代理的密码为 PASS
–referer=URL 在HTTP请求中包含 `Referer: URL’头
-s, –save-headers 保存HTTP头到文件
-U, –user-agent=AGENT 设定代理的名称为 AGENT而不是 Wget/VERSION
–no-http-keep-alive 关闭 HTTP活动链接 (永远链接)
–cookies=off 不使用 cookies
–load-cookies=FILE 在开始会话前从文件 FILE中加载cookie
–save-cookies=FILE 在会话结束后将 cookies保存到 FILE文件中

FTP 选项参数:

-nr, –dont-remove-listing 不移走 `.listing’文件
-g, –glob=on/off 打开或关闭文件名的 globbing机制
–passive-ftp 使用被动传输模式 (缺省值).
–active-ftp 使用主动传输模式
–retr-symlinks 在递归的时候,将链接指向文件(而不是目录)

递归下载参数:

-r, –recursive 递归下载--慎用!
-l, –level=NUMBER 最大递归深度 (inf 或 0 代表无穷)
–delete-after 在现在完毕后局部删除文件
-k, –convert-links 转换非相对链接为相对链接
-K, –backup-converted 在转换文件X之前,将之备份为 X.orig
-m, –mirror 等价于 -r -N -l inf -nr
-p, –page-requisites 下载显示HTML文件的所有图片

递归下载中的包含和不包含(accept/reject):

-A, –accept=LIST 分号分隔的被接受扩展名的列表
-R, –reject=LIST 分号分隔的不被接受的扩展名的列表
-D, –domains=LIST 分号分隔的被接受域的列表
–exclude-domains=LIST 分号分隔的不被接受的域的列表
–follow-ftp 跟踪HTML文档中的FTP链接
–follow-tags=LIST 分号分隔的被跟踪的HTML标签的列表
-G, –ignore-tags=LIST 分号分隔的被忽略的HTML标签的列表
-H, –span-hosts 当递归时转到外部主机
-L, –relative 仅仅跟踪相对链接
-I, –include-directories=LIST 允许目录的列表
-X, –exclude-directories=LIST 不被包含目录的列表
-np, –no-parent 不要追溯到父目录
wget -S –spider url 不下载只显示过程

4.使用实例

实例1:使用wget下载单个文件

命令:
wget http://www.minjieren.com/wordpress-3.1-zh_CN.zip

说明:
以下的例子是从网络下载一个文件并保存在当前目录,在下载的过程中会显示进度条,包含(下载完成百分比,已经下载的字节,当前下载速度,剩余下载时间)。

实例2:使用wget -O下载并以不同的文件名保存

命令:
wget -O wordpress.zip http://www.minjieren.com/download.aspx?id=1080

说明:
wget默认会以最后一个符合”/”的后面的字符来命令,对于动态链接的下载通常文件名会不正确。

错误:下面的例子会下载一个文件并以名称download.aspx?id=1080保存
wget http://www.minjieren.com/download?id=1
即使下载的文件是zip格式,它仍然以download.php?id=1080命令。

正确:为了解决这个问题,我们可以使用参数-O来指定一个文件名:
wget -O wordpress.zip http://www.minjieren.com/download.aspx?id=1080

实例3:使用wget –limit -rate限速下载

命令:
wget --limit-rate=300k http://www.minjieren.com/wordpress-3.1-zh_CN.zip

说明:
当你执行wget的时候,它默认会占用全部可能的宽带下载。但是当你准备下载一个大文件,而你还需要下载其它文件时就有必要限速了。

实例4:使用wget -c断点续传

命令:
wget -c http://www.minjieren.com/wordpress-3.1-zh_CN.zip

说明:
使用wget -c重新启动下载中断的文件,对于我们下载大文件时突然由于网络等原因中断非常有帮助,我们可以继续接着下载而不是重新下载一个文件。需要继续中断的下载时可以使用-c参数。

实例5:使用wget -b后台下载

命令:
wget -b http://www.minjieren.com/wordpress-3.1-zh_CN.zip

说明:
对于下载非常大的文件的时候,我们可以使用参数-b进行后台下载。

wget -b http://www.minjieren.com/wordpress-3.1-zh_CN.zip
Continuing in background, pid 1840.
Output will be written to `wget-log’.

你可以使用以下命令来察看下载进度:
tail -f wget-log

实例6:伪装代理名称下载

命令:

wget --user-agent=“Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16” http://www.minjieren.com/wordpress-3.1-zh_CN.zip

说明:
有些网站能通过根据判断代理名称不是浏览器而拒绝你的下载请求。不过你可以通过–user-agent参数伪装。

实例7:使用wget –spider测试下载链接

命令:
wget --spider URL

说明:
当你打算进行定时下载,你应该在预定时间测试下载链接是否有效。我们可以增加–spider参数进行检查。

wget --spider URL
如果下载链接正确,将会显示

wget --spider URL
Spider mode enabled. Check if remote file exists.
HTTP request sent, awaiting response… 200 OK
Length: unspecified [text/html]
Remote file exists and could contain further links,
but recursion is disabled – not retrieving.

这保证了下载能在预定的时间进行,但当你给错了一个链接,将会显示如下错误

wget --spider url
Spider mode enabled. Check if remote file exists.
HTTP request sent, awaiting response… 404 Not Found
Remote file does not exist – broken link!!!

你可以在以下几种情况下使用spider参数:
定时下载之前进行检查
间隔检测网站是否可用
检查网站页面的死链接

实例8:使用wget –tries增加重试次数

命令:
wget --tries=40 URL

说明:
如果网络有问题或下载一个大文件也有可能失败。wget默认重试20次连接下载文件。如果需要,你可以使用–tries增加重试次数。

实例9:使用wget -i下载多个文件

命令:
wget -i filelist.txt

说明:
首先,保存一份下载链接文件

cat > filelist.txt
url1
url2
url3
url4

接着使用这个文件和参数-i下载

实例10:使用wget –mirror镜像网站

命令:
wget --mirror -p --convert-links -P ./LOCAL URL

说明:
下载整个网站到本地。
–miror:开户镜像下载
-p:下载所有为了html页面显示正常的文件
–convert-links:下载后,转换成本地的链接
-P ./LOCAL:保存所有文件和目录到本地指定目录

实例11:使用wget –reject过滤指定格式下载

命令:
wget --reject=gif ur

说明:
下载一个网站,但你不希望下载图片,可以使用以下命令。

实例12:使用wget -o把下载信息存入日志文件

命令:
wget -o download.log URL

说明:
不希望下载信息直接显示在终端而是在一个日志文件,可以使用

实例13:使用wget -Q限制总下载文件大小

命令:
wget -Q5m -i filelist.txt

说明:
当你想要下载的文件超过5M而退出下载,你可以使用。注意:这个参数对单个文件下载不起作用,只能递归下载时才有效。

实例14:使用wget -r -A下载指定格式文件

命令:
wget -r -A.pdf url

说明:
可以在以下情况使用该功能:
下载一个网站的所有图片
下载一个网站的所有视频
下载一个网站的所有PDF文件

实例15:使用wget FTP下载

命令:

wget ftp-url
wget --ftp-user=USERNAME --ftp-password=PASSWORD url

说明:
可以使用wget来完成ftp链接的下载。

使用wget匿名ftp下载:
wget ftp-url

使用wget用户名和密码认证的ftp下载
wget --ftp-user=USERNAME --ftp-password=PASSWORD url

备注:编译安装
使用如下命令编译安装:

tar zxvf wget-1.9.1.tar.gz
cd wget-1.9.1
./configure
make
make install

TinyProxy: 提升 WGET 速度 / 优化国内机器出口通讯

为了解决国内的各种网络问题,真的是费劲了脑汁(例如 wget git……)

现提供 TinyProxy 解决方案

您可能需要

  • 一台墙外服务器

如何安装?

# Ubuntu
apt-get update
apt-get install tinyproxy -y

# CentOS
yum install tinyproxy -y

您需要调味料

  • 编辑 /etc/tinyproxy.conf
  • 也可能是 /etc/tinyproxy/tinyproxy.conf
  • 不同的系统,文件目录存在差异
Port 25
MaxClients 100
Allow 127.0.0.1
  • Port 是 TinyProxy 的监听端口,建议修改为 25 ,此为邮件端口,避免 QoS?
  • MaxClients 最大客户端链接数
  • Allow 是服务器的 IP 限制,请务必将 Allow 127.0.0.1 注释掉

重启 TinyProxy

/etc/init.d/tinyproxy restart

#顺带提一下其他
#启动:
/etc/init.d/tinyproxy start
#停止:
/etc/init.d/tinyproxy stop
#重启:
/etc/init.d/tinyproxy restart
#重载:
/etc/init.d/tinyproxy reload

使用

您可以使用以下命令使 Shell 使用之前搭建好的代理

export http_proxy=127.0.0.1:10086
export https_proxy=127.0.0.1:10086
export ftp_proxy=127.0.0.1:10086
  • 127.0.0.1 为您代理服务器的 IP
  • 10086 为您此前设置 TinyProxy 的监听端口

其他

  • 如果您遇到 403 等报错,请检查您的设置的 端口 否被占用

Linux实用工具总结之UFW

UFW,即Uncomplicated Firewall,是基于iptables实现的防火墙管理工具,所以实际上UFW修改的是iptables的规则。之所以不直接使用iptables,而要通过UFW进行管理是因为iptables的规则对于新手入门来说有点难,UFW做了很好的包装。
本文测试环境为Ubuntu 16.04,其他系统可做参考。

Ubuntu系统默认已经安装了UFW,如果没有ufw,可以手动安装:

$ sudo apt-get update
$ sudo apt-get install ufw

允许UFW管理IPV6

sudo vim /etc/default/ufw

确保你的IPV6选项为yes即可:

...
IPV6=yes
...

设置默认规则

UFW默认情况下允许所有的出站连接,拒绝所有的入站连接,所以这里首先将UFW设置为默认规则:

$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing

ufw default也允许使用reject参数

允许SSH连接

一旦启用UFW之后,如果没有允许SSH连接,将无法再通过SSH远程访问主机,所以在开启防火墙之后要确认SSH连接已经设置为允许:

$ sudo ufw allow ssh

这里创建一条规则,允许ssh连接,其实是允许22端口的连接,等价于:

$ sudo ufw allow 22

UFW通过/etc/services知道ssh服务使用的默认端口为22,如果你的SSH服务使用的端口不是22,则应该修改为相应 的端口号。

查看防火墙状态

通过以下命令查看防火墙状态:

$ sudo ufw status verbose

也可以不带verbose,当防火墙处于关闭状态时只会显示inactive
可以查看刚刚添加的防火墙规则:

$ sudo ufw show added

show后面还可以跟其他几项参数,可以通过man手册查看REPORTS

启用UFW命令:

$ sudo ufw enable

该命令默认会将UFW设置为开机启动,如果发现重启后UFW并没有自动启动,可以手动设置UFW服务开机自动启动:

$ sudo systemctl start ufw
$ sudo systemctl enable ufw

记得查看防火墙当前的状态:

$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
22                         ALLOW       Anywhere
22 (v6)                    ALLOW       Anywhere (v6)

禁用UFW:

$ sudo ufw disable

该命令会禁用防火墙并关闭其开机自动启动

启用防火墙日志:

$ sudo ufw logging on

可以指定日志级别sudo ufw logging low|medium|high
日志文件在/var/log/ufw.log
内容形如:

Sep 16 15:08:14 <hostname> kernel: [UFW BLOCK] IN=eth0 OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:00:00 SRC=123.45.67.89 DST=987.65.43.21 LEN=40 TOS=0x00 PREC=0x00 TTL=249 ID=8475 PROTO=TCP SPT=48247 DPT=22 WINDOW=1024 RES=0x00 SYN URGP=0

其中前面列出了主机防火墙日志的日期、时间、主机名,后面的内容意思是:

  • [UFW BLOCK]:表示事件描述的开始以及是何种事件。在此例中,它表示阻止了连接。
  • IN:如果它包含一个值,那么代表该事件是传入事件
  • OUT:如果它包含一个值,那么代表事件是传出事件
  • MAC:目的地和源 MAC 地址的组合
  • SRC:IP数据包的源IP
  • DST:目的地的IP
  • LEN:数据包长度
  • TTL:数据 TTL,或称为time to live。
  • PROTO:数据包的协议
  • SPT:数据包的源端口
  • DPT:目标端口
  • WINDOW:发送方可以接收的数据包的大小
  • SYN URGP:指示是否需要三次握手。 0 表示不需要。

禁用防火墙日志:

$ sudo ufw logging off

默认情况下ufw的allow不加in允许连接是指允许入站连接,如果要指定允许出站,可以加上out,如:

$ sudo ufw allow in port #允许port入站
$ sudo ufw allow out port #允许port出站

允许指定端口的所有连接协议

通过刚才设置ssh的规则,可以知道直接allow就是允许连接
允许HTTP 80端口的所有连接:

$ sudo ufw allow http

等价于:

$ sudo ufw allow 80

同样可以允许https的连接:

$ sudo ufw allow https

等价于:

$ sudo ufw allow 443

允许指定端口的指定协议连接

FTP默认端口为21,连接协议为tcp,那么可以这样:

$ sudo ufw allow ftp

等价于:

$ sudo ufw allow 21/tcp

允许指定范围内的端口的指定协议的连接

例如,X11的连接端口范围是6000-6007:

$ sudo ufw allow 6000:6007/tcp
$ sudo ufw allow 6000:6007/udp

允许指定IP的连接

通过查看防火墙状态可以看出有个From:

$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
22                         ALLOW       Anywhere                  
21/tcp                     ALLOW       Anywhere                  
22 (v6)                    ALLOW       Anywhere (v6)             
21/tcp (v6)                ALLOW       Anywhere (v6)

默认情况是相应端口允许所有IP的连接,可以通过后跟from指定允许某IP的所有连接:

$ sudo ufw allow from 15.15.15.51

允许15.15.15.51的所有入站连接,命令后面跟to any port 22允许端口22的所有连接:

$ sudo ufw allow from 15.15.15.51 to any port 22

允许子网的连接

如果要允许IP段15.15.15.1到15.15.15.254的所有连接:

$ sudo ufw allow from 15.15.15.0/24

并指定连接端口:

$ sudo ufw allow from 15.15.15.0/24 to any port 22

指定允许通过某个网卡的连接

通过命令中加入allow in on即可
首先查看系统中的所有网卡:

$ ip addr

或者:

$ ifconfig

假设这里允许eth0的80端口连接:

$ sudo ufw allow in on eth0 to any port 80

允许出站连接

允许相应端口的出站连接,直接allow后面跟out即可:

$ sudo ufw allow out 34

与允许连接一样,只需要将相应的allow换成deny即可,如拒绝http端口的所有连接:

$ sudo ufw deny http

等价于:

$ sudo ufw deny 80

拒绝指定ip的连接:

$ sudo ufw deny from 15.15.15.51

UFW有两种方式删除防火墙规则,既可以通过规则号删除,也可以通过实际规则删除,通过规则号删除更容易。

通过规则号删除

首先查看所有规则的规则号:

$ sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22                         ALLOW IN    Anywhere                  
[ 2] 21/tcp                     ALLOW IN    Anywhere                  
[ 3] 34                         ALLOW IN    Anywhere                  
[ 4] 34                         ALLOW OUT   Anywhere                   (out)
[ 5] 22                         ALLOW OUT   15.15.15.51                (out)
[ 6] 22 (v6)                    ALLOW IN    Anywhere (v6)             
[ 7] 21/tcp (v6)                ALLOW IN    Anywhere (v6)             
[ 8] 34 (v6)                    ALLOW IN    Anywhere (v6)             
[ 9] 34 (v6)                    ALLOW OUT   Anywhere (v6)              (out)

然后直接delete即可,例如删除ftp(21)的连接规则:

$ sudo ufw delete 2
$ sudo ufw delete 7

因为即有ipv6,又有ipv4,所以需要删除2个

通过规则删除

删除allow http规则:

$ sudo ufw delete allow http

等价于:

$ sudo ufw delete allow 80
$ sudo ufw reset

该命令将禁用UFW,并且删除所有已经定义的规则,不过默认该命令会对已经设置的规则进行备份

UFW的所有规则文件都在路径/etc/ufw/,其中before.rules规则为UFW在运行用户自定义的规则之前运行的规则,相应的before6.rules对应IPV6。after.rules为UFW启用用户自定义规则之后运行的规则。user.rules即为用户自定义的规则。
/etc/default/ufw文件为UFW的配置文件。
所以可以通过直接备份这些配置文件的方式来备份防火墙规则,需要备份的文件有:

/etc/ufw/*.rules
/lib/ufw/*.rules

/etc/default/ufw # 这个配置文件如果没有修改过,可以不备份
修改配置文件之后通过以下命令重新加载配置文件:

$ sudo ufw reload

批量禁止IP

$ while read line; do sudo ufw deny from $line; done < file.txt

file.txt里面是一个需要禁止的IP列表

Linux应用之crontab定时任务的设置

|实现Linux定时任务有:cron、anacron、at等,这里主要介绍cron服务。

名词解释:

cron是服务名称,crond是后台进程,crontab则是定制好的计划任务表。

软件包安装:

要使用cron服务,先要安装vixie-cron软件包和crontabs软件包,两个软件包作用如下:

vixie-cron软件包是cron的主程序。
crontabs软件包是用来安装、卸装、或列举用来驱动 cron 守护进程的表格的程序。

查看是否安装了cron软件包: rpm -qa|grep vixie-cron

查看是否安装了crontabs软件包: rpm -qa|grep crontabs

如果没有安装,则执行如下命令安装软件包(软件包必须存在)
rpm -ivh vixie-cron-4.1-54.FC5*
rpm -ivh crontabs*

如果本地没有安装包,在能够连网的情况下可以在线安装

yum install vixie-cron
yum install crontabs

查看crond服务是否运行:

pgrep crond

/sbin/service crond status

ps -elf|grep crond|grep -v "grep"

crond服务操作命令:

/sbin/service crond start //启动服务  
/sbin/service crond stop //关闭服务  
/sbin/service crond restart //重启服务  
/sbin/service crond reload //重新载入配置

配置定时任务:

cron有两个配置文件,一个是一个全局配置文件(/etc/crontab),是针对系统任务的;一组是crontab命令生成的配置文件(/var/spool/cron下的文件),是针对某个用户的.定时任务配置到任意一个中都可以。

查看全局配置文件配置情况: cat /etc/crontab

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# run-parts
01 * * * * root run-parts /etc/cron.hourly
02 4 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly

查看用户下的定时任务:crontab -l或cat /var/spool/cron/用户名

crontab任务配置基本格式:

*   *  *  *  *  command
分钟(0-59) 小时(0-23) 日期(1-31) 月份(1-12) 星期(0-6,0代表星期天)  命令

第1列表示分钟1~59 每分钟用*或者 */1表示
第2列表示小时1~23(0表示0点)
第3列表示日期1~31
第4列表示月份1~12
第5列标识号星期0~6(0表示星期天)
第6列要运行的命令

在以上任何值中,星号(*)可以用来代表所有有效的值。譬如,月份值中的星号意味着在满足其它制约条件后每月都执行该命令。

整数间的短线(-)指定一个整数范围。譬如,1-4 意味着整数 1、2、3、4。
用逗号(,)隔开的一系列值指定一个列表。譬如,3, 4, 6, 8 标明这四个指定的整数。
正斜线(/)可以用来指定间隔频率。在范围后加上 / 意味着在范围内可以跳过 integer。譬如,0-59/2 可以用来在分钟字段定义每两分钟。间隔频率值还可以和星号一起使用。例如,*/3 的值可以用在月份字段中表示每三个月运行一次任务。
开头为井号(#)的行是注释,不会被处理。

例子:

0 1 * * * /home/testuser/test.sh
每天晚上1点调用/home/testuser/test.sh

*/10 * * * * /home/testuser/test.sh
每10钟调用一次/home/testuser/test.sh

30 21 * * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每晚的21:30重启apache。

45 4 1,10,22 * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每月1、10、22日的4 : 45重启apache。

10 1 * * 6,0 /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每周六、周日的1 : 10重启apache。

0,30 18-23 * * * /usr/local/etc/rc.d/lighttpd restart
上面的例子表示在每天18 : 00至23 : 00之间每隔30分钟重启apache。

0 23 * * 6 /usr/local/etc/rc.d/lighttpd restart
上面的例子表示每星期六的11 : 00 pm重启apache。

* */1 * * * /usr/local/etc/rc.d/lighttpd restart
每一小时重启apache

* 23-7/1 * * * /usr/local/etc/rc.d/lighttpd restart
晚上11点到早上7点之间,每隔一小时重启apache

0 11 4 * mon-wed /usr/local/etc/rc.d/lighttpd restart
每月的4号与每周一到周三的11点重启apache

0 4 1 jan * /usr/local/etc/rc.d/lighttpd restart
一月一号的4点重启apache

*/30 * * * * /usr/sbin/ntpdate 210.72.145.44
每半小时同步一下时间

配置用户定时任务的语法:

crontab [-u user]file

crontab [-u user] [-l| -r | -e][-i]

参数与说明:

crontab -u//设定某个用户的cron服务

crontab -l//列出某个用户cron服务的详细内容

crontab -r//删除没个用户的cron服务

crontab -e//编辑某个用户的cron服务

例子:

假设当前用户是root,要建立root用户的定时任务

crontab -e

选择编辑器,编辑定时任务(这里假设是编辑器是vi)

按i进入编辑模式

0 1 * * * /root/test.sh

按esc退出编辑模式进入普通模式,输入:x或:wq保存退出

查看刚刚输入的定时任务

crontab -l 或 cat /var/spool/cron/root

根用户以外的用户可以使用 crontab 工具来配置 cron 任务。所有用户定义的 crontab 都被保存在 /var/spool/cron 目录中,并使用创建它们的用户身份来执行。要以某用户身份创建一个 crontab 项目,登录为该用户,然后键入 crontab -e 命令,使用由 VISUAL 或 EDITOR 环境变量指定的编辑器来编辑该用户的 crontab。该文件使用的格式和 /etc/crontab 相同。当对 crontab 所做的改变被保存后,该 crontab 文件就会根据该用户名被保存,并写入文件 /var/spool/cron/username 中。

cron 守护进程每分钟都检查 /etc/crontab 文件、etc/cron.d/ 目录、以及 /var/spool/cron 目录中的改变。如果发现了改变,它们就会被载入内存。这样,当某个 crontab 文件改变后就不必重新启动守护进程了。

重启crond:

/sbin/service crond restart

查看cron服务是否起作用:

如果我们要查看定时任务是否准时调用了可以/var/log/cron中的运行信息

cat /var/log/cron

grep .*.sh /var/log/cron

搜索.sh类型文件信息

sed -n '/back.*.sh/p' /var/log/cron

格式sed -n ‘/字符或正则表达式/p’ 文件名

我们在日志中查看在约定的时间是否有相应的调用信息,调用信息类似:

Sep 19 1:00:01 localhost crond[25437]: (root) CMD (/root/test.sh)

查看shell脚本是否报错:

如果/var/log/cron中准时调用了shell脚本,而又没有达到预期结果,我们就要怀疑shell脚本是否出错

cat /var/spool/mail/用户名

例子:

cat /var/spool/mail/root

test.sh

#!/bin/sh

echo "$(date '+%Y-%m-%d %H:%M:%S') hello world!" >> /root/test.log

要追踪shell调用的全过程:

bash -xv test.sh 2>test.log

test.sh的调用过程都会写到test.log中

改写test.sh

#!/bin/sh

set -xv

echo "$(date '+%Y-%m-%d %H:%M:%S') hello world!" >> /root/test.log

sh ./test.sh 2>tt.log

网上查询到的资料crontab不执行的问题:

第一,脚本的原因:大多数情况下,我们要相信科学,相信计算机,不是有鬼,就是我们的脚本的问题,这种问题导致crontab不能执行的概率占到 70%以上。因为程序执行到某一步导致crontab终止执行,我就碰到一次在迁移代码的时候将数据库连错了。导致无法访问而死在那里了。

第二,执行环境问题,当我们碰到第一情况下,一般都可以通过手动执行程序将问题扼杀在摇篮里,一般情况下高手是不应该犯第一种错误的。问题是当我们 手动执行成功而crontab不能执行的时候,笔者碰到一次就是执行环境的问题,例如相关路径的设置问题。解决方案:在代码最前面执行 source /home/user/.bash_profile

第三,系统时间不正确。这种问题最好理解,也是比较常见和隐蔽的问题,解决方案:date -s ********

第四,就是我们的脚本是否有可执行权限。必须保证执行脚本的用户有执行改文件的权限。

第五,crontab 守护进程死掉了。这种情况是极少发生的,但也不排除,当我们实在是找不到其他原因的时候可以用。解决方案:重启该进程。

第六,crontab不执行的问题困扰了好长时间,脚本写的都正确,但是就是不执行,最终解决方法如下:
crontab -u root /var/spool/cron/root
这样root用户的crontab就生效了
service crond restart
重启下服务就好了

第七,crond没有启动

第八,脚本编码问题,脚本在window下编写,传到linux下后报“锘?!/bin/bash”,用vi编辑器新建新shell脚本,输入内容后保存。

crontab定时任务命令

crontab命令被用来提交和管理用户的需要周期性执行的任务,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具,并且会自动启动crond进程,crond进程每分钟会定期检查是否有要执行的任务,如果有要执行的任务,则自动执行该任务。

语法

crontab(选项)(参数)

选项

-e:编辑该用户的计时器设置;
-l:列出该用户的计时器设置;
-r:删除该用户的计时器设置;
-u<用户名称>:指定要设定计时器的用户名称。

参数

crontab文件:指定包含待执行任务的crontab文件。

知识扩展

Linux下的任务调度分为两类:系统任务调度和用户任务调度。

系统任务调度:系统周期性所要执行的工作,比如写缓存数据到硬盘、日志清理等。在/etc目录下有一个crontab文件,这个就是系统任务调度的配置文件。

/etc/crontab文件包括下面几行:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=""HOME=/

# run-parts
51 * * * * root run-parts /etc/cron.hourly
24 7 * * * root run-parts /etc/cron.daily
22 4 * * 0 root run-parts /etc/cron.weekly
42 4 1 * * root run-parts /etc/cron.monthly

前四行是用来配置crond任务运行的环境变量,第一行SHELL变量指定了系统要使用哪个shell,这里是bash,第二行PATH变量指定了系统执行命令的路径,第三行MAILTO变量指定了crond的任务执行信息将通过电子邮件发送给root用户,如果MAILTO变量的值为空,则表示不发送任务执行信息给用户,第四行的HOME变量指定了在执行命令或者脚本时使用的主目录。

用户任务调度:用户定期要执行的工作,比如用户数据备份、定时邮件提醒等。用户可以使用 crontab 工具来定制自己的计划任务。所有用户定义的crontab文件都被保存在/var/spool/cron目录中。其文件名与用户名一致,使用者权限文件如下:

/etc/cron.deny     该文件中所列用户不允许使用crontab命令
/etc/cron.allow    该文件中所列用户允许使用crontab命令
/var/spool/cron/   所有用户crontab文件存放的目录,以用户名命名

crontab文件的含义:用户所建立的crontab文件中,每一行都代表一项任务,每行的每个字段代表一项设置,它的格式共分为六个字段,前五段是时间设定段,第六段是要执行的命令段,格式如下:

minute   hour   day   month   week   command     顺序:分 时 日 月 周

其中:

  • minute: 表示分钟,可以是从0到59之间的任何整数。

  • hour:表示小时,可以是从0到23之间的任何整数。

  • day:表示日期,可以是从1到31之间的任何整数。

  • month:表示月份,可以是从1到12之间的任何整数。

  • week:表示星期几,可以是从0到7之间的任何整数,这里的0或7代表星期日。

  • command:要执行的命令,可以是系统命令,也可以是自己编写的脚本文件。

在以上各个字段中,还可以使用以下特殊字符:

  • 星号(*):代表所有可能的值,例如month字段如果是星号,则表示在满足其它字段的制约条件后每月都执行该命令操作。

  • 逗号(,):可以用逗号隔开的值指定一个列表范围,例如,“1,2,5,7,8,9”

  • 中杠(-):可以用整数之间的中杠表示一个整数范围,例如“2-6”表示“2,3,4,5,6”

  • 正斜线(/):可以用正斜线指定时间的间隔频率,例如“0-23/2”表示每两小时执行一次。同时正斜线可以和星号一起使用,例如*/10,如果用在minute字段,表示每十分钟执行一次。

crond服务

/sbin/service crond start    //启动服务
/sbin/service crond stop     //关闭服务
/sbin/service crond restart  //重启服务
/sbin/service crond reload   //重新载入配置

查看crontab服务状态:

service crond status

手动启动crontab服务:

service crond start

查看crontab服务是否已设置为开机启动,执行命令:

ntsysv

加入开机自动启动:

chkconfig –level 35 crond on

实例

每1分钟执行一次command

* * * * * command

每小时的第3和第15分钟执行

3,15 * * * * command

在上午8点到11点的第3和第15分钟执行

3,15 8-11 * * * command

每隔两天的上午8点到11点的第3和第15分钟执行

3,15 8-11 */2 * * command

每个星期一的上午8点到11点的第3和第15分钟执行

3,15 8-11 * * 1 command

每晚的21:30重启smb

30 21 * * * /etc/init.d/smb restart

每月1、10、22日的4 : 45重启smb

45 4 1,10,22 * * /etc/init.d/smb restart

每周六、周日的1:10重启smb

10 1 * * 6,0 /etc/init.d/smb restart

每天18 : 00至23 : 00之间每隔30分钟重启smb

0,30 18-23 * * * /etc/init.d/smb restart

每星期六的晚上11:00 pm重启smb

0 23 * * 6 /etc/init.d/smb restart

每一小时重启smb

* */1 * * * /etc/init.d/smb restart

晚上11点到早上7点之间,每隔一小时重启smb

* 23-7/1 * * * /etc/init.d/smb restart

每月的4号与每周一到周三的11点重启smb

0 11 4 * mon-wed /etc/init.d/smb restart

一月一号的4点重启smb

0 4 1 jan * /etc/init.d/smb restart

每小时执行/etc/cron.hourly目录内的脚本

01 * * * * root run-parts /etc/cron.hourly

一个 crontab 定时任务的 bug

本来利用 cron 任务是每小时运行一次,但是不小心弄错了,搞成每分钟运行一次。

* */1 * * * cd ~/Wechatscope && R CMD BATCH wechatscope.R

这实际上是每一个小时的每一分钟。

未分类

把分钟改成具体的数值就好。

1 */1 * * * cd ~/Wechatscope && R CMD BATCH wechatscope.R

bug 详情
https://github.com/Terminus2049/Wechatscope/commit/41516059511098be6c46c5a1af24c445f82ef089

以后还是拿 https://crontab.guru/ 校验一下

可能这个 bug 是造成 http://wechatscope.jmsc.hku.hk/ 频繁下线的原因 ~-~