配置Tomcat修改代码项目自动重新部署

conf文件夹中

修改context.xml

Context标签添加一个属性

reloadable="true"

设置之后测试的时候

需要等待一会儿,和你修改web.xml的等待时间差不多

网上的教程有毒吧

WEB-INF下的web.xml

设置 <servlet> 标签中

<load-on-startup>0</load-on-startup>

利用ssh隧道解决登录vps服务器慢的问题

1. 背景

linode的vps在某些网络下访问比较慢,甚至还有丢包的情况。但是从国内的服务器ping过去,一切正常。之前听说过ssh端口转发及隧道特性,于是考虑在通过正常的国内服务器去登录vps。

2. 传统做法

先登录稳定服务器,然后在上面再通过ssh登录到目标机器。虽然简单直接,但这样的缺点也显而易见,证书管理不方便。

3. SSH隧道方式

这里是基于稳定服务器将vps的端口转发到了本地。

  • step1 先登录稳定服务器
    ssh -L 36000:VPS-IP:22 稳定服务器IP
    这里通过稳定服务器,将VPS的22端口转发到了本地的36000端口

  • step2 登录本地端口
    ssh -p 36000 localhost
    由于是转发,这里之前在VPS上配置的证书依然可以使用,只是换了一个端口和IP而已。

4. 其他使用场景

本地端口转发还有一个比较实用的场景,就是可以将服务器的内网端口转发到本地。比如,有些开发同学习惯通过本地的IDE连接远程的mysql,这样将数据库的远程访问权限打开有一定安全隐患。体验下另外一种方式:

# 先将远程服务器的192.168.2.110:3307端口映射到本地33070
ssh -L 33070:192.168.2.110:3307 跳板机IP
#登录本地33070端口,注意将host指定为127.0.0.1
mysql -P 33070 -h127.0.0.1 -uusername -p'password'

5. 其他转发方式

除了将远程端口转发到本地(Local Forwarding),还有两种方式:

  • 动态端口转发(Dynamic Forwarding)
    ssh -D [bind_addr]:port user@server
    适合代理方式

  • 远程端口转发(Remote Forwarding)
    ssh -R [bind_addr]:port:host:hostport user@server
    相当于将host:hostport映射到了server:port上

解决debian9系统安装后root用户无法通过ssh连接的问题

小L有一个hostigation 256d KVM小鸡在吃灰,今天没事拿出来折腾,看到后台居然有windows2008的系统可以安装,就手贱点了reinstall,安装不成功,显示初始化什么失败之类的。然后再后台面板看到最新出来的debian9的ROM,就挂载了重新安装,经过一番折腾终于安装成功,但是悲催的发现在本地的ssh下居然root用户无法登录,另外一个受限账户可以登录,未远程通过VNC却都可以登录。然后百度了一圈,网络上的解决方案都是针对debian8及以下的系统解决方案,按照这个方案修改做如下修改:

vi /etc.ssh/sshd_config

把文本中的

#PermitRootLogin no

前的“#”去掉”no”改成“yes”

然而,debian9的配置文件中并没有这段代码!仔细查看后把

#PermitRootLogin prohibit-password

改成

PermitRootLogin yes

并reboot后解决。

ssh连接失败的排错经验

一、场景描述

ssh连接服务器,发现连接失败,但是对应服务器的ip能够ping通。

场景:

[root@yl-web ~]# ssh [email protected]
ssh_exchange_identification: read: Connection reset by peer
[root@yl-web ~]# ping 10.1.101.35
PING 10.1.101.35 (10.1.101.35) 56(84) bytes of data.
64 bytes from 10.1.101.35: icmp_seq=1 ttl=64 time=0.587 ms
64 bytes from 10.1.101.35: icmp_seq=2 ttl=64 time=0.722 ms
64 bytes from 10.1.101.35: icmp_seq=3 ttl=64 time=0.475 ms

ping是一个网络层的协议,只是表面网络在3层是通的;

ssh是应用层协议,具体还是从主机上找原因。

二、排错

1、ssh -v

用ssh -v去连有问题的服务器,会有比较详细的调试信息在屏幕上输出,可以帮助判断是哪一步出了问题。

主要是看是客户端还是服务器的问题。如果是客户端的问题,应该log中有写。如果是没有什么有用信息,就可能是服务器端出问题了。

[root@yl-web ~]# ssh -v [email protected]
OpenSSH_6.6.1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 56: Applying options for *
debug1: Connecting to 10.1.101.35 [10.1.101.35] port 22.
debug1: Connection established.
debug1: permanently_set_uid: 0/0
debug1: identity file /root/.ssh/id_rsa type -1
debug1: identity file /root/.ssh/id_rsa-cert type -1
debug1: identity file /root/.ssh/id_dsa type -1
debug1: identity file /root/.ssh/id_dsa-cert type -1
debug1: identity file /root/.ssh/id_ecdsa type -1
debug1: identity file /root/.ssh/id_ecdsa-cert type -1
debug1: identity file /root/.ssh/id_ed25519 type -1
debug1: identity file /root/.ssh/id_ed25519-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.6.1
ssh_exchange_identification: read: Connection reset by peer

2、连接服务器

现在看起来是服务器出问题了,虽然不能ssh到服务器,但一般来说主机会提供一些方法比去让你连接,比如通过物理终端连进去,具体情况具体对待了,总之就是要连接到服务器上。

3、写一个排错弯路,但也是有用的

如果有debug1: Connection refused by tcp wrapper之类的log可参考这一步。

就是说你的客户端ip可能被服务器给禁掉了,fail2ban或者其他的程序可能把你的客户端ip扔到/etc/hosts.deny中了。

通过vi /etc/hosts.allow查看

未分类

加上一行sshd: ALL。

然后重启ssh。

#service sshd restart

如果问题真的出在ip被禁,这样重启之后应该就ok了。

客户端重新ssh试一下:

[root@yl-web ~]# ssh -v [email protected]
OpenSSH_6.6.1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 56: Applying options for *
debug1: Connecting to 10.1.101.35 [10.1.101.35] port 22.
debug1: connect to address 10.1.101.35 port 22: Connection refused
ssh: connect to host 10.1.101.35 port 22: Connection refused

说明我的问题不在这里。

4、两条有用的命令

在服务器上执行下面命令可以显示ssh的所有 log。

centos系统如下:

#service sshd stop
#/usr/sbin/sshd -d

如果是ubuntu可能命令是:

sudo service ssh stop ,sudo /usr/sbin/sshd -d。

未分类

问题出现了: /var/empty/sshd must be owned by root and not group or world-writable。

是权限的问题了,查看一下。

未分类

我的权限变成777了,而sshd这个目录

正常情况该目录的权限应该是:

[root@yl-web ~]# ll /var/empty/
total 0
drwx--x--x. 2 root root 6 May 13 03:41 sshd

修改权限:

未分类

改好权限后重启sshd服务【service sshd restart】。客户端再ssh就ok,大功告成了。

5、命令简介

至此问题已解决,但是/usr/sbin/sshd -d又是什么意思呢?

man sshd看一下这两个参数。

     -D      When this option is specified, sshd will not detach and does not become a daemon.  This allows easy monitoring of sshd.

     -d      Debug mode.  The server sends verbose debug output to standard error, and does not put itself in the background.  The server also will not fork and will only process one connection.  This
             option is only intended for debugging for the server.  Multiple -d options increase the debugging level.  Maximum is 3.

-d是debug模式,服务器会向屏幕输出详细的debug信息,服务器只能有一个ssh链接。

三、题外话

虽然问题解决了,回想一下为什么会出这个问题?因为我昨天在解决一个日志权限的问题时,暴力的将每层目录权限都设置成777,想试探一下是否是目录读写权限的问题,然后再缩小权限,结果影响到了ssh登录。

想想解决一个问题若不能知道原理,很容易放大问题,甚至出现新bug。写代码需谨慎,排错需谨慎,知其然不知其所以然很重要。

Azure Ubuntu VM + Squid + MySql 搭建用户可管理的代理服务器集群

本文介绍使用Squid 中的 basic_db_auth + mysql 作为Squid的用户权限认证模块,便于后期扩展与管理维护

VM的搭建

由于我们需要构建的是一个代理池,机器的数量可能很多,所以比较方便的做法是使用Azure的自定义镜像功能。一次搭建,多次复制。

  • 首先使用Azure Portal创建一个Ubuntu 虚拟机,代理所需要的资源比较少,一般最低配置的A0也就足够使用了。为安全起见建议使用PK/SK的方式设置登陆。

  • Squid安装:

sudo apt-get install squid -y
sudo systemctl status squid

如果看到squid正在运行的状态,则Squid安装成功

  • Squid配置:

Squid 配置文件路径: /etc/squid/squid.conf, 建议修改前先备份一份。基础配置可以参照:http://wiki.ubuntu.org.cn/Squid。

下面为本次我所用到的配置文件,配置文件中的连接字符串配置需要根据自己的需要更改。

auth_param basic program /usr/lib/squid/basic_db_auth --dsn "DBI:mysql:host=host;port=3306;database=database" --user "user" --password "pwd" --plaintext --persist --debug
auth_param basic children 1 startup=1 idle=1
auth_param basic realm gsbw proxy-caching web server
auth_param basic credentialsttl 10 minute
acl dbauth proxy_auth REQUIRED
acl SSL_ports port 443
acl Safe_ports port 80      # http
acl Safe_ports port 21      # ftp
acl Safe_ports port 443     # https
acl Safe_ports port 70      # gopher
acl Safe_ports port 210     # wais
acl Safe_ports port 1025-65535  # unregistered ports
acl Safe_ports port 280     # http-mgmt
acl Safe_ports port 488     # gss-http
acl Safe_ports port 591     # filemaker
acl Safe_ports port 777     # multiling http
acl CONNECT method CONNECT
http_access allow !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
http_access deny manager
http_access allow localhost
http_access allow dbauth
http_access deny all
http_port 3128
via off
forwarded_for transparent

注意使用Mysql认证的话需要安装perl的DBI包:

cpan
cpan>install DBI

配置好之后需要重启squid服务或者重新加载配置文件:

sudo systemctl restart squid

然后也不要忘记了在Azure安全组里面需要添加对 配置文件中 http_port 端口的入站权限。权限添加好之后就可以尝试下能否通过代理访问成功。

  • 捕获VM镜像:

在目标机器上取消设置源 VM

sudo waagent -deprovision+user -force
exit

然后使用azure cli操作,以下环境为azure cli 1.0:

azure config mode arm
azure login -e AzureChinaCloud -u username
azure vm deallocate -g myResourceGroup -n myVM
azure vm generalize -g myResourceGroup -n myVM
azure vm capture -g myResourceGroup -n myVM -p myVHDNamePrefix -t myTemplate.json

至此 我们的原始镜像已经创建成功。

批量创建虚拟机

azure group create myResourceGroup1 -l "chinaeast"
azure network vnet create myResourceGroup1 myVnet -l "chinaeast"
azure network vnet subnet create myResourceGroup1 myVnet mySubnet
azure network public-ip create myResourceGroup1 myPublicIP -l "chinaeast"
azure network nic create myResourceGroup1 myNIC -k mySubnet -m myVnet -p myPublicIP -l "chinaeast"
azure network nic show myResourceGroup1 myNIC
azure group deployment create myResourceGroup1 MyDeployment -f MyTemplate.json

我们还可以使用资源模板来创建更多的虚拟机。这部分可以参照官方文档。

快速创建一个可读写的Samba Server的shell脚本

把下面的内容保存成一个shell 脚本,运行完就有了一个可读写的samba server

#!/bin/bash
yum install samba samba-common samba-winbind -y
mv /etc/samba/smb.conf /etc/samba/smb.conf.backup

echo "  [global]    " > /etc/samba/smb.conf
echo "          workgroup = PXESERVER   " >> /etc/samba/smb.conf
echo "          server string = Samba Server Version %v " >> /etc/samba/smb.conf
echo "          log file = /var/log/samba/log.%m    " >> /etc/samba/smb.conf
echo "          max log size = 50   " >> /etc/samba/smb.conf
echo "          idmap config * : backend = tdb  " >> /etc/samba/smb.conf
echo "          cups options = raw  " >> /etc/samba/smb.conf
echo "          netbios name = pxe  " >> /etc/samba/smb.conf
echo "          map to guest = bad user " >> /etc/samba/smb.conf
echo "          dns proxy = no  " >> /etc/samba/smb.conf
echo "          public = yes    " >> /etc/samba/smb.conf
echo "          kernel oplocks = no " >> /etc/samba/smb.conf
echo "          nt acl support = no " >> /etc/samba/smb.conf
echo "          security = user " >> /etc/samba/smb.conf
echo "          guest account = nobody  " >> /etc/samba/smb.conf
echo "  [upload]    " >> /etc/samba/smb.conf
echo "          comment = upload    " >> /etc/samba/smb.conf
echo "          path = /home/upload " >> /etc/samba/smb.conf
echo "          read only = no  " >> /etc/samba/smb.conf
echo "          browseable = yes    " >> /etc/samba/smb.conf
echo "          public = yes    " >> /etc/samba/smb.conf
echo "          printable = no  " >> /etc/samba/smb.conf
echo "          guest ok = yes  " >> /etc/samba/smb.conf
echo "          oplocks = no    " >> /etc/samba/smb.conf
echo "          level2 oplocks = no " >> /etc/samba/smb.conf
echo "          locking = no    " >> /etc/samba/smb.conf

mkdir -p /home/upload
chmod -R 0755 /home/upload
chown -R nobody:nobody /home/upload
systemctl restart smb
systemctl enable smb

saltstack实现文件分发

取消配置文件/etc/salt/master以下注释

... ...
file_roots:
  base:
    - /srv/salt
... ...

新建相关目录

mkdir /srv/salt
touch /srv/salt/top.sls

top.sls文件 /srv/salt/top.sls

base:
  '*':
    - ssh_key.key
mkdir /srv/salt/ssh_key
touch /srv/salt/test.sls

/srv/salt/test.sls

/root/.ssh/authorized_keys: 
# 客户端文件存放路径和命名,如果.ssh目录不存在则会自动新建
  file:
    - managed
    - source: salt://ssh_key/test   
    # 默认file根目录为`/srv/salt`,拷贝相应文件至所在目录
    - user: root
    - group: root
    - mode: 600

最终目录结构

# tree /srv/salt/
/srv/salt/
|-- ssh_key
|   |-- test
|   |-- test.sls
`-- top.sl

server端主动推送

salt '*' state.highstate -v     # 按照top.sls执行所有
salt '*' state.sls ssh_key.ms   # 指定sls执行

rsync通过exclude排除多文件/目录实例

说明:

使用rsync -av –exclude=upload /home/mysql/backup /home/mysql/backup2/ 只能排除upload文件/目录。但如果要排除多个文件/目录,就需要新建个exclude.list,然后rsync -av –exclude-from=”exclude.list”指定不需要同步的文件/目录

实现:

# rsync -av --exclude-from=/root/exclude.list /home/mysql/backup /home/mysql/backup2/
//将/home/mysql/backup目录拷贝到/home/mysql/backup2目录下,/root/exclude.list中指定文件不拷贝。

注意exclude.list里面填写要排除的文件/目录,一行一个,直接写文件名即可。这里,可以把/home/mysql/backup看成根目录,所以如果要排除a,b.1,b.2,tmp/g,那么exclude.list里就应该写

a
b.*
tmp/g

而不是填写以下完整url。不然这样还是会同步a,b.1,b.2,tmp/g

/home/mysql/backup/a
/home/mysql/backup/b.*
/home/mysql/backup/tmp/g

当然以下这种写法也是会同步a,b.1,b.2,tmp/g文件的,也是有问题

./home/mysql/backup/a
./home/mysql/backup/b.*
./home/mysql/backup/tmp/g

使用python删除大文件中的特定行的最优算法

问题

1.a
2.ab
3.bc

文件如上所示,数字为行数。比如我需要删除内容为”a”的行,在大文件情况下,用何种语法最优?
其他编程语言也可推荐,谢谢。

最佳答案

with open('file.txt', 'r') as old_file:
    with open('file.txt', 'r+') as new_file:

        # 定位到需要删除的行,跳出循环时,seek_point 存放的是被删除行的行首的光标位置
        while True:
            # 记录光标位置
            seek_point = old_file.tell()

            if 'a' in old_file.readline().strip().split('.'):
                # 光标跳到被删除行的下一行行首
                break

        # 设置光标位置,光标在被删除行的行首
        new_file.seek(seek_point, 0)

        # 被删除行的下一行读给 next_line
        next_line = old_file.readline()

        # 连续覆盖剩余行,后面所有行上移一行
        while next_line:
            new_file.write(next_line)
            next_line = old_file.readline()

        # 写完最后一行后截断文件,因为删除操作,文件整体少了一行,原文件最后一行需要去掉
        new_file.truncate()