启动两个tomcat实例的方法

启动两个tomcat报错

为了开发方便,可能会前台和后台各跑一个Tomcat,但是会发现程序启动一般,然后报如下错(logs下日志可查看):

15-Mar-2017 11:13:40.889 严重 [main] org.apache.catalina.core.StandardService.initInternal Failed to initialize connector [Connector[AJP/1.3-8009]]
 org.apache.catalina.LifecycleException: Failed to initialize component [Connector[AJP/1.3-8009]]
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:112)
    at org.apache.catalina.core.StandardService.initInternal(StandardService.java:549)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:107)
    at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:875)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:107)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:606)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:629)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:311)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:494)
Caused by: org.apache.catalina.LifecycleException: Protocol handler initialization failed
    at org.apache.catalina.connector.Connector.initInternal(Connector.java:970)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:107)
    ... 12 more
Caused by: java.net.BindException: Address already in use: bind
    at sun.nio.ch.Net.bind0(Native Method)
    at sun.nio.ch.Net.bind(Net.java:344)
    at sun.nio.ch.Net.bind(Net.java:336)
    at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:199)
    at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
    at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:210)
    at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:972)
    at org.apache.tomcat.util.net.AbstractJsseEndpoint.init(AbstractJsseEndpoint.java:244)
    at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:558)
    at org.apache.catalina.connector.Connector.initInternal(Connector.java:968)
    ... 13 more

和如下错:

15-Mar-2017 11:13:41.965 严重 [main] org.apache.catalina.core.StandardServer.await StandardServer.await: create[localhost:8005]: 
 java.net.BindException: Address already in use: JVM_Bind
    at java.net.DualStackPlainSocketImpl.bind0(Native Method)
    at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:96)
    at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:374)
    at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:175)
    at java.net.ServerSock
    et.bind(ServerSocket.java:376)
    at java.net.ServerSocket.<init>(ServerSocket.java:237)
    at org.apache.catalina.core.StandardServer.await(StandardServer.java:440)
    at org.apache.catalina.startup.Catalina.await(Catalina.java:743)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:689)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:355)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:495)

解决办法

出现这种问题,想到的解决办法当然是到conf文件夹下找到server.xml更改端口号,只是这次更改,不仅要修改(本人默认端口号已改为8081):

<Connector port="8081" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

并且修改如下两个端口,一个在以上端口的上方,一个在下方(其中的端口号都是自己改过的)

<Server port="8055" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
<Connector port="8099" protocol="AJP/1.3" redirectPort="8443" />

意思该文档里的三个端口号都更改。

安装证书配置Tomcat支持https访问

安装证书

Tomcat支持JKS格式证书,从Tomcat7开始也支持PFX格式证书,两种证书格式任选其一。

文件说明:

  • 证书文件214216134950893.pem,包含两段内容,请不要删除任何一段内容。

  • 如果是证书系统创建的CSR,还包含:证书私钥文件214216134950893.key、PFX格式证书文件214216134950893.pfx、PFX格式证书密码文件pfx-password.txt。

1、证书格式转换

在Tomcat的安装目录下创建cert目录,并且将下载的全部文件拷贝到cert目录中。如果申请证书时是自己创建的CSR文件,附件中只包含214216134950893.pem文件,还需要将私钥文件拷贝到cert目录,命名为214216134950893.key;如果是系统创建的CSR,请直接到第2步。

到cert目录下执行如下命令完成PFX格式转换命令,此处要设置PFX证书密码,请牢记:

openssl pkcs12 -export -out 214216134950893.pfx -inkey 214216134950893.key -in 214216134950893.pem

2、PFX证书安装

找到安装Tomcat目录下该文件server.xml,一般默认路径都是在 conf 文件夹中。找到 <Connection port=”8443″ 标签,增加如下属性:

keystoreFile="cert/214216134950893.pfx"
keystoreType="PKCS12"
#此处的证书密码,请参考附件中的密码文件或在第1步中设置的密码
keystorePass="证书密码"

完整的配置如下,其中port属性根据实际情况修改:

<Connector port="8443"
    protocol="HTTP/1.1"
    SSLEnabled="true"
    scheme="https"
    secure="true"
    keystoreFile="cert/214216134950893.pfx"
    keystoreType="PKCS12"
    keystorePass="证书密码"
    clientAuth="false"
    SSLProtocol="TLSv1+TLSv1.1+TLSv1.2"
    ciphers="TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256"/>

3、JKS证书安装(帮助)

  • 使用java jdk将PFX格式证书转换为JKS格式证书(windows环境注意在%JAVA_HOME%/jdk/bin目录下执行)
keytool -importkeystore -srckeystore 214216134950893.pfx -destkeystore your-name.jks -srcstoretype PKCS12 -deststoretype JKS

回车后输入JKS证书密码和PFX证书密码,强烈推荐将JKS密码与PFX证书密码相同,否则可能会导致Tomcat启动失败。

  • 找到安装 Tomcat 目录下该文件Server.xml,一般默认路径都是在 conf 文件夹中。找到 <Connection port=”8443″ 标签,增加如下属性:
keystoreFile="cert/your-name.jks"
keystorePass="证书密码"

完整的配置如下,其中port属性根据实际情况修改:

<Connector port="8443"
    protocol="HTTP/1.1"
    SSLEnabled="true"
    scheme="https"
    secure="true"
    keystoreFile="cert/your-name.jks"
    keystorePass="证书密码"
    clientAuth="false"
    SSLProtocol="TLSv1+TLSv1.1+TLSv1.2"
    ciphers="TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256"/>

( 注意:不要直接拷贝所有配置,只需添加 keystoreFile,keystorePass等参数即可,其它参数请根据自己的实际情况修改 )

4、 重启 Tomcat

5、 通过 https 方式访问您的站点

测试站点证书的安装配置,如遇到证书不信任问题,请查看帮助视频。

Docker安装配置tomcat jdk

第一步:将tomcat及JDK 复制到指定目录 /docker/

未分类

第二步:在该目录下编写Dockerfile文件,进行添加进行文件内容

未分类

第三步:编译Dockerfile文件

docker build -t tomcat .

build :表示编译Dockerfile文件

-t tomcat :表示 镜像文件名称为tomcat,这里可以自己定义名称

. : 一定要记住点 . 表示当前目录

未分类

第四步:查看是否生成镜像文件

docker images

未分类

第五步:创建启动容器

docker create –name item_tomcat -p 8080:8080 tomcat

–name item_tomcat : 表示给容器创建一个名称,可以自定义

-p 8080:8080 :表示指定容器端口与本机端口对应,访问的时候会自动调整到指定容器端口8080

tomcat:表示使用哪个镜像文件进行创建容器

未分类

第六步:启动容器

docker start item_tomcat

未分类

第七步:查看启动容器日志

docker logs item_tomcat

未分类

第八步:访问tomcat启动是否成功

浏览器https://localhost:8080

未分类

或者使用命令直接访问 curl https://localhost:8080

未分类

Docker容器部署启动已经完成。

Tomcat和JVM的性能调优总结

就算生不逢时,也该理解理解了。对于一些性能调优的话题我是一直插不上嘴,只是针对昨晚看到的一篇性能调优的文章,我忍不住了。

Tomcat性能调优

找到Tomcat根目录下的conf目录,修改server.xml文件的内容。对于这部分的调优,我所了解到的就是无非设置一下Tomcat服务器的最大并发数和Tomcat初始化时创建的线程数的设置,当然还有其他一些性能调优的设置,下图是我根据我机子的性能设置的一些参数值,给各位详细解释一下吧:

未分类

1、URIEncoding=”UTF-8″ :设置Tomcat的字符集。这种配置我们一般是不会设置的,因为关于乱码的转换我们会在具体项目中具体处理,直接修改Tomcat的字符集未免过于太死板。

2、maxThreads=”300″ :设置当前Tomcat的最大并发数。Tomcat默认配置的最大请求数是150个,即同时能支持150个并发。但是在实际运用中,最大并发数与硬件性能和CPU数量都有很大关系的,更好的硬件、更高的处理器都会使Tomcat支持更多的并发数。如果一般在实际开发中,当某个应用拥有 250 个以上并发的时候,都会考虑到应用服务器的集群。

3、minSpareThreads=”50″ :设置当前Tomcat初始化时创建的线程数,默认值为25。

4、acceptCount=”250″ :当同时连接的人数达到maxThreads参数设置的值时,还可以接收排队的连接数量,超过这个连接的则直接返回拒绝连接。指定当任何能够使用的处理请求的线程数都被使用时,能够放到处理队列中的请求数,超过这个数的请求将不予处理。默认值为100。在实际应用中,如果想加大Tomcat的并发数 ,应该同时加大acceptCount和maxThreads的值。

5、enableLookups=”false” :是否开启域名反查,一般设置为false来提高处理能力,它的取值还有true,一般很少使用。

6、maxKeepAliveRequests=”1″ :nginx动态的转给tomcat,nginx是不能keepalive的,而tomcat端默认开启了keepalive,会等待keepalive的timeout,默认不设置就是使用connectionTimeout。 所以必须设置tomcat的超时时间,并关闭tomcat的keepalive。否则会产生大量tomcat的socket timewait。 maxKeepAliveRequests=”1”就可以避免tomcat产生大量的TIME_WAIT连接,从而从一定程度上避免tomcat假死。

JVM性能调优

Tomcat本身还是运行在JVM上的,通过对JVM参数的调整我们可以使Tomcat拥有更好的性能。目前针对JVM的调优主要有两个方面:内存调优和垃圾回收策略调优。

内存调优  

找到Tomcat根目录下的bin目录,设置catalina.sh文件中JAVA_OPTS变量即可,因为后面的启动参数会把JAVA_OPTS作为JVM的启动参数来处理。再说Java虚拟机的内存结构是有点复杂的,相信很多人在理解上都是很抽象的,它主要分为堆、栈、方法区和垃圾回收系统等几个部分组成,下面是我从网上扒的内存结构图:

未分类

内存调优这块呢,无非就是通过修改它们各自的内存空间的大小,使应用能够更加合理的运用,下图是我根据我机子的性能设置的参数,给各位详细解释一下各个参数的含义吧:

未分类

1、-Xmx512m :设置Java虚拟机的堆的最大可用内存大小,单位:兆(m),整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m。堆的不同分布情况,对系统会产生一定的影响。尽可能将对象预留在新生代,减少老年代GC的次数(通常老年回收起来比较慢)。实际工作中,通常将堆的初始值和最大值设置相等,这样可以减少程序运行时进行的垃圾回收次数和空间扩展,从而提高程序性能。

2、-Xms512m :设置Java虚拟机的堆的初始值内存大小,单位:兆(m),此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。

3、-Xmn170m :设置年轻代内存大小,单位:兆(m),此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。一般在增大年轻代内存后,也会将会减小年老代大小。

4、-Xss128k :设置每个线程的栈大小。JDK5.0以后每个线程栈大小为1M,以前每个线程栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。

5、 -XX:NewRatio=4 :设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5 。

6、-XX:SurvivorRatio=4 :设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6。

7、-XX:MaxPermSize=16m :设置持久代大小为16m,上面也说了,持久代一般固定的内存大小为64m。

8、-XX:MaxTenuringThreshold=0:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。

垃圾回收策略调优  

找到Tomcat根目录下的bin目录,也是设置catalina.sh文件中JAVA_OPTS变量即可。我们都知道Java虚拟机都有默认的垃圾回收机制,但是不同的垃圾回收机制的效率是不同的,正是因为这点我们才经常对Java虚拟机的垃圾回收策略进行相应的调整。下面也是通过我的一些需求来配置的垃圾回收策略:

未分类

Java虚拟机的垃圾回收策略一般分为:串行收集器、并行收集器和并发收集器。

串行收集器:

1、-XX:+UseSerialGC:代表垃圾回收策略为串行收集器,即在整个扫描和复制过程采用单线程的方式来进行,适用于单CPU、新生代空间较小及对暂停时间要求不是非常高的应用上,是client级别默认的GC方式,主要在JDK1.5之前的垃圾回收方式。

并发收集器:

1、-XX:+UseParallelGC:代表垃圾回收策略为并行收集器(吞吐量优先),即在整个扫描和复制过程采用多线程的方式来进行,适用于多CPU、对暂停时间要求较短的应用上,是server级别默认采用的GC方式。此配置仅对年轻代有效。该配置只能让年轻代使用并发收集,而年老代仍旧使用串行收集。

2、-XX:ParallelGCThreads=4:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。

3、-XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0支持对年老代并行收集 。

4、-XX:MaxGCPauseMillis=100 :设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。

5、-XX:+UseAdaptiveSizePolicy:设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开。

并发收集器:

1、-XX:+UseConcMarkSweepGC:代表垃圾回收策略为并发收集器。

好了,到此我对虚拟机的垃圾回收策略总结就这么多,还是这句话:优化的学习一直在路上,下面还有一张从其他博客中偷到的图,据说以上三种GC机制是需要配合使用的。

未分类

Tomcat的catalina.out日志分割

一、背景

Tomcat 的 catalina.out 日志量不断增加,占用空间较大,且默认是不滚动的。因此,需要对其进行日志分割,并进行清理。

本文选用 Cronolog 对其进行分割。

二、安装

1、下载

地址:http://cronolog.org/download/cronolog-1.6.2.tar.gz

2、安装

# tar zxvf cronolog-1.6.2.tar.gz
# cd cronolog-1.6.2
# ./configure
# make
# make install

3、测试

查看 cronolog 安装后所在目录,验证安装是否成功:

# which cronolog

一般情况下显示为:/usr/local/sbin/cronolog

三、配置

1、修改文件

2、修改内容

  • 第一步
if [ -z "$CATALINA_OUT" ] ; then
CATALINA_OUT="$CATALINA_BASE"/logs/catalina.out

改为

if [ -z "$CATALINA_OUT" ] ; then
CATALINA_OUT="$CATALINA_BASE"/logs/catalina.%Y-%m-%d.log
  • 第二步
touch "$CATALINA_OUT"

改为

#touch "$CATALINA_OUT"
  • 第三步
org.apache.catalina.startup.Bootstrap "$@" start 
>> "$CATALINA_OUT" 2>&1 "&"

改为

org.apache.catalina.startup.Bootstrap "$@" start 2>&1 
|/usr/local/sbin/cronolog "$CATALINA_OUT" >> /dev/null &
  • 第四步
org.apache.catalina.startup.Bootstrap "$@" start 
>> "$CATALINA_OUT" 2>&1 "&"

改为

org.apache.catalina.startup.Bootstrap "$@" start 2>&1 
|/usr/local/sbin/cronolog "$CATALINA_OUT" >> /dev/null &

四、重启

重启后,查看日志是否分割成功。

如何使用Python和BeautifulSoup抓取网页

网络上的信息是任何人穷极一生也无法全部了解的。你需要的或许不是简单的获得信息,而是一个可以收集,整理,分析信息,并且具有拓展性的方法。

你需要网页抓取(Web scraping)技术

网页抓取可以自动提取网站上的数据信息,并把这些信息用一种容易理解的格式呈现出来。网页抓取应用广泛, 在本教程中我们将重点讲解它在金融市场领域的运用。

如果你是个投资达人,每天查找收盘价一定是个烦心事,更不用提数据来源于多个网站的时候。我们可以用代码写一个网络爬虫 (web scraper) 来帮助我们自动从网站获取股指信息,从而大大简化数据提取过程。
范例+代码:一文带你上手Python网页抓取神器BeautifulSoup库-数据分析网

未分类

我们开始吧。

我们采用Python进行网页数据抓取,并采用简单强大的BeautifulSoup 库完成分析。

  • 对于Mac用户来说, OS X操作系统已经预先安装好Python。您需要打开终端并输入python –version。您应该可以看到python的版本为2.7.x。
  • 对于Windows用户而言,请由官方网站安装Python。

下一步,我们需要利用pip命令获取BeautifulSoup 库。Pip 是Python中管理库和包的工具。

在终端中输入:

easy_install pip  
pip install BeautifulSoup4

注意:如果您不能运行上面的命令,在每行前面加上sudo 再试试。

基础知识

在学习代码之前,让我们先来了解HTML的基础知识和网页抓取的基本规则。

标签

如果你已经充分理解HTML标签,请跳过这一部分

<!DOCTYPE html>  
<html>  
    <head>
    </head>
    <body>
        <h1> First Scraping </h1>
        <p> Hello World </p>
    <body>
</html>

这就是HTML网页的基本语法。

每一对标签内包含网页的一段代码:

  • <!DOCTYPE html> : HTML 文件必须以文件类型声明开头

  • HTML文件包含在 <html> 和 <html/> 标签之间

  • 元(meta)和脚本(script)声明包含在 <head> 和 </head> 标签之间

  • 网站上可见的部分包含在 <body> 和 </body> 标签之间

  • <h1> 和 <h6> 标签之间的部分为网站标题

  • <p> 标签用于定义段落

其他有用的标签还有: <a> 是超链接的标签, <table> 是表格的标签, <tr> 是表格行的标签, <td> 是表格列的标签。

并且,HTML标签常常带有标识码(id) 或类(class)属性,标识码用来唯一的识别某个HTML标签,并且标识码的值在整个HTML文件中是唯一的。类属性可以定义同类HTML标签相同的样式。我们可以利用标识码和类来帮助我们定位想要的数据。

如果您想了解关于HTML标签,标识码和类的更多内容,请参考W3Schools 出品的教程。

网络抓取规则

  • 在您进行网络抓取时,你应该查看网站的条款和条件。请仔细阅读数据合法使用声明。通常情况下,您抓取的数据不能商用。

  • 您的程序不要过于频繁的向网站发出数据请求(也被称为垃圾请求),这种做法可能会使网站崩溃。请确保您的程序行为合理(也就是说和人类的行为相似)。对一个网站每秒进行一次数据请求是比较好的做法。

  • 网站的布局随时间不断变化,所以请您确保时常重新访问网站,如果需要的话,修改抓取代码。

查看页面

让我们以Bloomberg Quote网站的其中一页为例。

作为一个关注股票市场的投资人,我们想要从这一页得到股指名称(标准普尔500指数)和价格。首先,右键点击打开浏览器的检查器(inspector),查看网页。

未分类

请尝试把光标放在股指价格上,你应该可以看到价格周围的蓝色方块,如果你点击这个方块,就可以选中浏览器控制台相应的HTML代码。

未分类

从结果可以看出,价格信息包含在好几层HTML标签中:<div> → <div> → <div>.

同样的,如果你把光标放在名称“标准普尔指数“上,并点击,可以看到控制台里这个信息包含在标签 < iv> 及 < h1> 之内。

未分类

现在我们知道如何依靠类标签找到我们需要的数据了。

学习代码

现在我们知道所需数据的位置,我们可以开始写代码构建我们的网络爬虫了。现在请打开您的文字编辑工具!

首先我们要导入我们要用的各种库。

# 导入各种库

import urllib2

from bs4 import BeautifulSoup

然后,我们定义一个变量(quote_page)并赋值为网站的网址链接。

# 赋值网站链接

quote_page = ‘http://www.bloomberg.com/quote/SPX:IND'

接着,利用Python的urllib2库获取方才定义的网址quote_page的 HTML网页信息。

# 检索网站并获取html代码,存入变量”page”中

page = urllib2.urlopen(quote_page)

最后,我们把网页解析为 BeautifulSoup格式,以便我们用BeautifulSoup 库来分析网页。

# 用 beautifulSoup 解析HTML代码并存入变量“soup”中`

soup = BeautifulSoup(page, ‘html.parser’)

现在我们有了包含整个网页的HTML代码的变量soup。我们就从soup开始着手提取信息。

别忘了我们的数据存储在特有的层次中。BeautifulSoup库中的find()函数可以帮助我们进入不同的层次提取内容。我们需要的HTML类“名称”在整个网页中是独一无二的,因此我们可以简单的查找 < div>

# 获取“名称”类的<div>代码段落并提取相应值

name_box = soup.find(‘h1’, attrs={‘class’: ‘name’})

在我们得到标签之后,我们可以用name_box的text属性获取相应值

name = name_box.text.strip() # strip() 函数用于去除前后空格

print name

采用相似的方法,我们可以得到股指价格数据。

# 获取股指价格数据

price_box = soup.find(‘div’, attrs={‘class’:’price’})

price = price_box.text

print price

未分类

当你运行程序时,应该可以看到程序输出当前的标普500指数的价格。

导出Excel CSV格式数据

我们已经学会如何获取数据,现在来学习如何存储数据了。Excel逗号隔开的数据格式(CSV)不失为一个好选择。这样我们就可以在Excel中打开数据文件进行查看和进一步处理。

在此之前,我们需要导入Python的csv模块和datetime模块。Datetime模块用于获取数据记录时间。请将下面几行代码插入您的导入代码部分。

import csv

from datetime import datetime

在您代码的最下方,加上把数据写入CSV文件的代码。

# 以“添加”模式打开一个csv文件, 以保证文件原有信息不被覆盖

with open(‘index.csv’, ‘a’) as csv_file:

writer = csv.writer(csv_file)

writer.writerow([name, price, datetime.now()])

未分类

现在如果运行程序,您应该可以导出一个index.csv文件。您可以在Excel中打开文件,看到里面有如图所示的一行数据。

所以如果您每天都运行这个程序,您就可以很简单的获取标准普尔指数价格,不需要像之前一样在网站上翻找。

更进一步(高级用法)

多个股指

抓取一个股指信息对您来说不够,对吗?我们可以试试同时提取多个股指信息。首先,我们需要修改quote_page,把它定义为网址的数组。

quote_page = [‘http://www.bloomberg.com/quote/SPX:IND', ‘http://www.bloomberg.com/quote/CCMP:IND']

然后我们把数据提取部分代码改成一个for循环。这个循环可以一一处理网址,并以元组(tuple)类型把所有数据存入变量data.

# for 循环

data = []

for pg in quote_page:

# 检索网站并返回HTML代码,存入变量‘page’ 

page = urllib2.urlopen(pg)

# 用 beautifulSoup 解析HTML代码并存入变量 `soup`

soup = BeautifulSoup(page, ‘html.parser’)

# 获取“名称”类的<div>代码段落并提取相应值

name_box = soup.find(‘h1’, attrs={‘class’: ‘name’})

name = name_box.text.strip() # strip() is used to remove starting and trailing

# 获取股指价格数据

price_box = soup.find(‘div’, attrs={‘class’:’price’})

price = price_box.text

# 用元组类型存储数据

data.append((name, price))

并且,修改保存部分以便一行行保存数据

# 以“添加”模式打开一个csv文件, 以保证文件原有信息不被覆盖 

with open(‘index.csv’, ‘a’) as csv_file:

writer = csv.writer(csv_file)

# for 循环

for name, price in data:

writer.writerow([name, price, datetime.now()])

重新运行程序,您应该可以同时提取两个股指价格信息了!

高级抓取技术

BeautifulSoup 库使用简单,能很好的完成小量的网站抓取。但是如果您对大量的抓取信息感兴趣,您可以考虑其他方法:

  • 强大的Python数据抓取框架Scrapy。

  • 您可以试试把一些公共应用程序接口(Application programming interface, API) 整合入您的代码。这个获取数据的方法远比网页抓取高效。举个例子来说,您可以试试Facebook Graph API,这个应用程序接口可以帮助您获取脸书网站上不显示的隐藏信息。

  • 如果数据量过大,您可以考虑使用类似MySQL的数据库后端来存储数据。
    采取“别重复”方法

未分类

DRY是“别重复你做过的事”的英文简写。您可以尝试像链接中的这个人一样把日常的工作自动化。同时您还可以考虑其他有趣的项目,比如说掌握您的脸书好友的上线时间(当然在征得他们同意的情况下),或者获取某个论坛的讲座主题列表来尝试自然语言处理(这是目前人工智能的热门话题)!

原文链接:https://medium.freecodecamp.org/how-to-scrape-websites-with-python-and-beautifulsoup-5946935d93fe

SSH如何反向代理稳定穿透内网

未分类

最近在测试一些站点,总是需要进入到对方内网,而使用的代理工具多为不稳定工具,就连ssh也会断掉,这篇文章分享一下SSH的反向代理,最下面准备啦一个简单的脚本。

0x01 引言

早期我们可能会采用HTTP Proxy代理,在浏览器上设置下代理服务器的IP、端口、认证账户和密码。但有些软件的网络通信数据并不是HTTP协议,就需要寻找其它方法。

SOCKS代理是个不错的解决方案,不管应用层是什么协议,只要是传输层是TCP协议就可以代理。SOCKS代理中最新的协议是SOCKS5。相对SOCKS4作了大幅度的增强。

首先,它增加了对UDP协议的支持;其次,可支持多种用户身份验证方式和通信加密方式;最后,修改了SOCKS服务器进行域名解析的方法,使其更加优雅。

0x02 Socks建立

关于内网的代理工具前人已经总结很多了比如这篇文章内网漫游之SOCKS代理大结局,那我就不多说这些工具了。

稳定SOCKS代理SSH

SSH当之无愧是目前最稳定的代理方式之一,大家用它比较多,但是我们常用的还是他的最简单的转发与正向代理的建立,这里把SSH反向代理分享与大家,不用再为渗透中不稳定的网络而烦恼。

转发

我们常用的是下面的命令,但只能够比较麻烦的访问到已经转发端口上

ssh -CfNg -R 2222:127.0.0.1:22 VPS-user@VPS -p 53 //内网 
ssh -CfNg -L 8080:127.0.0.1:2222 VPS-user@VPS //VPS 本地访问VPS:8080就是内网的22端口
-C:该参数将使ssh压缩所有通过Secure Shell客户端发送的数据,包括输入、输出、错误消息及转发数据。它使用gzip算法,压缩级别可通过设置配制文件中的参数Compressicn Level来指定。这对于缓慢的传输线路特别有用的。但对于传输速度已经很快的网络则显得没有必要。同样,你可以利用配制文件针对每台主机配置这个参数。 
-f:该参数将ssh连接送入后台执行。这在验证已经完成且TCP/IP转发已经建立的情况下会生效。这对在远程主机上启动X程序显得十分重要。其后用户将被提示要求输入口令(提供的认证代理不运行),然后将连接送往后台。 
-g:该参数允许远程主机通过端口转发与主机端口相连,通常情况下仅允许本地主机这样做。 
-N:不执行远程指令。 
-R:远程转发 
-L:本地转发

socks正向代理

下面的方式可以用与你与DMZ区的机器通信,但是如果不能直接访问的内网机器便行不通了。

ssh -qTfnN -D port remotehost
在本地终端中运行 
ssh -qTfnN -D 6080 user@theserver 
然后在浏览器或者软件中设置好代理参数 
socks5: 127.0.0.1:6080 后便可以使用.
-q:静默运行

其实已经很明显了,反向代理就是把上面提到的两个隧道连接在一起,怎么连接呢?

socks反向代理

那么重点来了,如何建立反向代理呢?其实就是把正向代理和转发结合起来即可:

这里为了方便描述,截了几个图,画得丑见笑了…:

未分类

第一步,还是先通过内网机器反向连接VPS:

ssh -p 22 -qngfNTR 6666:localhost:22 VPS-user@VPS

这样就把本地的22端口转发到了远程机器(VPS)的6666端口

查看图中Server机器的进程:

未分类

Server机器转发:

未分类

此时到vps上查看已经在6666端口开始监听了

未分类

第二步,你自己的PC机器直接使用语句:

ssh -p 6666 -qngfNTD 6767 内网用户@VPS

这样就可以直接穿透网络,进入到内网,本地机器直接使用代理127.0.0.1:6767便能够直接访问到内网当中

本地远程访问:

未分类

在Server上开启80端口服务

未分类

配置代理:

未分类

访问:

未分类

进阶配置

那么问题来了,用过SSH的代理的朋友应该知道,我们第一步使用的连接方式在VPS监听的6666端口应该是监听在localhost上的,那么在第一步之前就应该修改一些配置了:在VPS的ssh配置当中加入如下配置GatewayPorts yes,这里是指远程转发过来的端口监听在0.0.0.0上。当然也可以你再在VPS本地转发一次即可。

这样就完了吗?当然没有,经过测试,我们是无法让这个代理保持一直在线的,SSH在一定时间没有任何的操作后就会自动的断开,那么我们同样再次修改配置文件:

找到 ClientAliveInterval 0和ClientAliveCountMax 3并将注释符号(”#”)去掉, 将ClientAliveInterval对应的0改成60,ClientAliveInterval指定了服务器端向客户端请求消息的时间间隔, 默认是0,不发送. ClientAliveInterval 60表示每分钟发送一次, 然后客户端响应, 这样就保持长连接了. ClientAliveCountMax, 使用默认值3即可.ClientAliveCountMax表示服务器发出请求后客户端没有响应的次数达到一定值, 就自动断开. 这样的配置就能让一个SSH的配置保持长连接了,代理就能稳定的在线。那么这样是需要每次都输入密码而且每次输入一大堆命令很麻烦,这里写了一个简单的CentOS上使用脚本来开启代理。

#!/usr/bin/env bash
#author: rootclay
export HISTSIZE=0
#install
cd /etc/yum.repos.d/ 
wget http://download.opensuse.org/repositories/home:Strahlex/CentOS_CentOS-6/home:Strahlex.repo 
yum install -y sshpass 
yum install -y screen
mkdir /tmp/mongo && chown $(whoami):$(whoami) /tmp/mongo 
sudo tee /tmp/mongo/daemon.sh <<-'EOF'

#!/usr/bin/env bash
while: 
do 
    /usr/bin/sshpass -p 你的VPS密码 ssh -p 22 -qngfNTR 6770:localhost:22 
    VPS-user@VPS -o StrictHostKeyChecking=no 
    sleep 18000 
    ps -ef | grep qngfNTR | awk '{print $2}' | xargs kill -9 
done 
EOF

chmod +x /tmp/mongo/daemon.sh 
echo "screen -dmS test /tmp/mongo/daemon.sh" >> /etc/rc.d/rc.local 
screen -dmS socks /tmp/mongo/daemon.sh 
useradd test;echo 'test:1234' | chpasswd
/usr/local/bin/sshpass -p "1234" ssh -p 6770 -qngfNTD 6770 test@VPS -o 
StrictHostKeyChecking=no 
本地执行执行这条命令即可,代理设置为127.0.0.1:6770即可进入内网

这样建立起来的socks网络是非常的稳定的,搭建了之后可以试一试开扫描器扫一扫,高线程都不会掉。。。而前面使用的比如EW之类的。。。一扫就挂=。=,这个开个高线程完全没问题。

squid透明代理之应用层广告过滤

透明代理的意思是客户端不需要知道有代理服务器的存在,也不需要有设置代理的操作,它改变你的request fields(报文),并会传送真实IP。

什么时候用透明代理?

squid正向代理其实我一直都在用,在局域网做个缓存服务器常用网站的加载速度会有明显提升,我主要还是为了在应用层过滤广告,可是移动设备设置代理又比较麻烦,一个网段下的其他人也不能受益,这种情况就可以搞起 “透明代理了“(https://baike.so.com/doc/1191007-1259770.html) 。

当然如果想了解局域网内的其他人都上了哪些不可告人的网站,刷朋友圈浏览了哪些照片。这时squid相当于是个中间人,对于裸奔的http请求,那绝对毫无隐私可言啊,结合一些日志分析工具譬如awstats,可以很直观的了解局域网内设备的浏览行文,当然这一切对于客户端是透明的无感知的。这也是为什么现在如此推崇ssl的原因了。对于https squid 其实也是可以解析的,就是比较麻烦这个后面再说。

准备物料

  • 树莓派,我这用的树莓派2b+;

  • 路由器,华为pro;

squid

squid安装过程不表仅贴一下编译参数,具体可参见官方文档

./configure --prefix=/usr/local/squid 
--enable-gnuregex 
--disable-carp 
--enable-async-io=240 
--with-pthreads 
--enable-storeio=ufs,aufs,diskd 
--disable-wccp 
--enable-icmp 
--enable-kill-parent-hack 
--enable-cachemgr-hostname=Raspi 
--with-maxfd=65535 
--enable-poll 
--enable-Linux-netfilter  #透明代理必需
--enable-large-cache-files 
--disable-ident-lookups 
--enable-default-hostsfile=/etc/hosts 
--with-dl 
--with-large-files 
--enable-delay-pools 
--enable-snmp 
--disable-internal-dns 
--enable-underscore 
--enable-arp-acl

当然你如果想让squid承担中间人重新加密的任务(就是解析https数据拉),就需要增加以下两个参数了,让squid支持sslbump和动态证书生成,但是这种方式仅支持正向代理。

--with-openssl
--enable-ssl-crtd

具体可以参照以下官方文档:

  • http://wiki.squid-cache.org/Features/SslBump

  • http://wiki.squid-cache.org/Features/DynamicSslCert

  • http://wiki.squid-cache.org/Features/MimicSslServerCert

squid装好后有几个关键配置

vim /usr/local/squid/etc/squid.conf
http_port 3128 transparent #开启透明代理支持
cache_mem 128 MB
logformat combined %>a %ui %un [%tl] "%rm %ru HTTP/%rv" %Hs %<st "%{Referer}>h" "%{User-Agent}>h" %Ss:%Sh #combined格式输出日志,后面awstats统计用
access_log /data/logs/squid/access.log combined #后面awstats统计要用到
cache_log /data/logs/squid/cache.log

#广告过滤
error_directory /usr/local/squid/share/errors/en-us/ #指定错误信息语言,我这里是英文(广告请求拦截后的转发页面也放这里)
acl deny_url dstdom_regex "/usr/local/squid/etc/acl/deny_url.acl" #广告url列表,github上有很多如 https://github.com/vokins/yhosts
deny_info 410:ERR_URL deny_url #ERR_URL是error_directory目录下面的错误文件,可以是文本或者html文件。 http_access deny deny_url

squid常用命令

/usr/local/squid/sbin/squid -z #重建缓存
/usr/local/squid/sbin/squid #启动
/usr/local/squid/sbin/squid -k reconfigure #重载配置文件

如果一切顺利此时squid的透明代理已经支持。

dhcp

但是要让整个局域网使用透明代理,还需让客户端的网关地址是squid服务器的地址,网关地址在普通路由器上是没法自定义的。

你可以关闭路由器的dhcp功能,路由器就当ap来使用,在树莓派上搭建一个dhcp服务,这里用的是isc-dhcp-server

apt-get直接安装

apt-get install isc-dhcp-server

编辑配置文件

vim /etc/dhcp/dhcpd.conf
subnet 10.0.0.0 netmask 255.255.255.0 {
  range 10.0.0.10 10.0.0.100;
  option domain-name-servers 180.76.76.76;
  option domain-name "qiananhua.com";
  option routers 10.0.0.2; #squid主机地址
#  option broadcast-address 10.0.0.255;
  default-lease-time 86400;
  max-lease-time 172800;
}
service isc-dhcp-server restart

断开wifi重新连接即可。

iptables

最后一步让经过squid服务器网卡的http 80端口流量用squid服务的3128端口处理

转发

iptables -t nat -A PREROUTING -s 10.0.0.0/24 -p tcp --dport 80 -j REDIRECT --to-port 3128

如果一切顺利此时打开 www.163.com 你看到的页面应该是这样的

未分类

awstats

安装比较简单如图所示

未分类

配置文件需要指定LogFile为squid日志文件地址

vim /etc/awstats/awstats.squid.conf
LogFile="/data/logs/squid/access.log"

手动生成下结果页面-dir=指定生成到nginx配置的虚拟主机根目录

/usr/local/awstats/tools/awstats_buildstaticpages.pl -update -config=squid -lang=cn -dir=/data/htdocs/awstats -awstatsprog=/usr/local/awstats/wwwroot/cgi-bin/awstats.pl

当然也可以吧这条命令放到.sh文件里添加到crontab自动执行,比如每30分钟执行一次统计

*/30 * * * * /data/shell/awstats.sh > /dev/null 2>&1

接着nginx添加一个awstats的虚拟主机

vim /usr/local/nginx/conf/vhosts/awstats.conf
server {
    listen 80;
    server_name awstats;
    access_log /data/logs/nginx/awstats.log;
    root /data/htdocs/awstats;
        index awstats.squid.html;

        location ~ ^/icon/{
                root /usr/local/awstats/wwwroot;
        }
}

注意本地修改下host,不出意外你会看到以下页面(最后一张图http状态吗410就是被过滤的广告链接了,占比还挺大)

未分类

未分类

未分类

CentOS7安装配置Squid http代理

其实之前配过一个squid,只是由于太懒,网上随便搜了一个教程,用了默认端口并且没有添加用户认证。某天不幸的被爬虫扫到,被用来发了半个月的垃圾邮件。。直到有一天登录邮箱,看到了一大坨警告邮件,才意识到问题的严重。惊了个呆之后,赶紧重配一遍-.-

我这里是用squid配置了一个带用户认证的普通代理。

安装

安装过程十分简便,只需要安装一下squid,一条命令搞定。我这里装的是squid3.3。

yum install squid

rpm -qa | grep squid
squid-3.3.8-12.el7_0.x86_64

配置

修改squid的配置文件 /etc/squid/squid.conf

主要就是配置一下端口,缓存,日志和访问规则。

http_port 3712
cache_mem 64 MB
maximum_object_size 4 MB
cache_dir ufs /var/spool/squid 100 16 256
access_log /var/log/squid/access.log
http_access allow all
visible_hostname squid.chao

初始化

在第一次启动之前或者修改了cache路径之后,需要重新初始化cache目录。

squid -z

启动

systemctl start squid

使用

  • 在浏览器中修改代理配置即可。

  • 在windows中:

    • Internet选项 -> 连接 -> 局域网连接 -> 代理服务器
  • 在macOSX中:
    • Safari -> 偏好设置 -> 代理 -> Web代理

然后输入你的代理地址和端口,就可以正常工作了。

测试

我从网上看到一个非常简单的方法,可以用来快速测试你的代理是否正常工作。首先打开百度,然后搜索ip。如果出来的是你代理的那台机器的ip,那么恭喜你,一大波垃圾邮件即将赶来。

添加用户认证

为了防止我们的代理被爬虫扫到并且被用于不法用途,我们非常有必要为我们的squid添加用户认证。事实上我刚配的代理,没过多久就已然被扫到。

我从我的access.log里面看到。然而此时我还没有添加任何认证机制,幸好我没使用认端口,不然我的邮箱又会收到一大坨告警邮件了。。

1439106533.703      0 89.102.9.196 TCP_DENIED/403 3739 GET http://www2.praguerentacar.com/proxy/detectproxy.php - HIER_NONE/- text/html
1439106539.302      0 89.102.9.196 TCP_DENIED/403 3724 GET http://www2.intimnosti.cz/proxy/detectproxy.php - HIER_NONE/- text/html
1439106544.881      0 89.102.9.196 TCP_DENIED/403 3706 GET http://93.185.96.50/proxy/detectproxy.php - HIER_NONE/- text/html
1439106550.453      0 89.102.9.196 TCP_DENIED/403 3712 GET http://www2.nuabi.com/proxy/detectproxy.php - HIER_NONE/- text/html

我们这里通过ncsa认证模块来为我们的squid添加认证。为什么我选择ncsa呢,因为我从网上搜到的大多用了这个方式。。

首先我们得配置我们的访问用户的账户信息。最后一个参数是用户名,可以替换成任何你喜欢的名字~

htpasswd -c /etc/squid/passwd chao

如果找不到htpasswd,就先装个Apache。yum install httpd。 然后就能使用htpasswd了。

有了帐户文件之后,我们重新配置我们的squid。在squid.conf里面,把

http_access allow all

改成

auth_param basic program /usr/lib64/squid/basic_ncsa_auth /etc/squid/passwd
auth_param basic children 5
auth_param basic realm chao's squid server
auth_param basic credentialsttl 2 hours
acl myacl proxy_auth REQUIRED
http_access allow myacl
http_access deny all

最后重启squid就可以啦。

systemctl restart squid

现在当你使用代理访问页面的时候,会先弹出一个提示框,让你输入用户名密码。然后就可以继续访问了。

配置说明

有些人可能一开始对原理以及配置的详细介绍并不感冒,只是想让代理先跑起来再说。至少我本人就是这样子的。。所以,我把这块放在了最后。

现在,就开始介绍一下上面配置的具体内容。当然参考 官网(http://www.squid-cache.org/Doc/config/) 会更加详细准确。

http_port 3712 这个指定了我们代理的端口

cache_mem 64 MB 内存中的缓存大小

cache_dir ufs /var/spool/squid 100 16 256 缓存文件夹,默认是只在内存中进行缓存的。这里指定缓存大小为100M,第一层子目录为16个,第二层为256。

maximum_object_size 4 MB 最大被缓存文件大小,这个配合上面的cache_dir使用,只作用于缓存到磁盘的文件。

access_log /var/log/squid/access.log 访问日志

auth_param basic program /usr/lib64/squid/basic_ncsa_auth /etc/squid/passwd 指定认证程序以及账户文件

auth_param basic children 5 认证程序同时跑的个数

auth_param basic realm chao's squid server 客户端在使用代理时,输入密码时弹出来的提示框中的描述文字。

auth_param basic credentialsttl 2 hours 认证的持续时间

acl myacl proxy_auth REQUIRED 对myacl使用外部程序进行认证

http_access allow myacl 允许myacl中的成员访问

http_access deny all 拒绝所有其它访问

visible_hostname squid.chao 代理机名字

ubuntu16.04安装配置samba服务器

ubuntu16.04上samba服务器的安装和配置
samba服务器的介绍可以查看鸟哥私房菜服务篇中的文件服务器之二,有详细的介绍,本文只介绍samba的两种安装方式和配置。

1. 离线安装

  • 下载samba压缩包samba-3.0.22-tar.gz

  • 解压到目标目录,如/opt

  • 解压之后,进入到source目录,执行以下命令

./configure
make
make install
  • 修改配置文件,将example/samba.conf.default 拷贝到/usr/local/samba/lib,将其名称修改为samba.conf,写入的配置信息如下:
[global]
workgroup = Linux # 在windows上显示的目录名称
netbios name = test 
server string = Linux Samba Server TextServer
Security = share # 安全等级

[Linux]
path = /root  # 共享/root目录
writeable = yes # 写的权限
browsable = yes # 查看的权限
guest ok = yes # 访客身份

设置以guest身份登录,无需密码。

2. 在线安装

  • 在命令行中输入:
sudo apt-get install samba samba-common-bin
  • 进入/etc/samba目录,修改smb.conf配置文件,只需要将[home]块的注释取消即可,共享/home文件夹

  • 将当前用户添加到samba访客中:

sudo smbpasswd -a username

输入两次密码。

3. 启动服务

命令行输入:

smbd
nmbd
  • windows连接采用:\ip

  • linux连接采用:smbclient -L //ip