醉梦轩

醉中无日月,梦里有乾坤

0x00 前言

通常一个脚本都是使用某一种语言编写,使用固定的解释器执行。例如以下这段vbs脚本:

1
WScript.echo("Hello World!")

可以使用wscriptcscript执行,但肯定不能使用cmd或其他程序执行。

是否可以构造这样一种脚本,能同时被多种解释器执行呢?

阅读全文 »

0x00 前言

mongodb是一款基于分布式文件存储的数据库,具有高性能、可扩展、易部署、易使用等特点。官方也提供了丰富的命令行工具来操作。

阅读全文 »

0x00 前言

有很多Python语言的协程库,如:tornado、asyncio等。这些库在使用时需要使用特定的语法,如:async/await,对于非协程的代码需要改写才能以协程方式运行。

gevent是一个特殊的协程库,它可以将非协程代码以协程方式运行,从而起到提升性能的作用。本文尝试分析一下它的实现原理。

阅读全文 »

0x00 前言

Javascript中的prototype是一个十分重要的概念,但是网上的教程一般分析得比较绕,结果越看越晕,反而变得更加难以理解了。

本文尝试由浅入深,从实验入手,来深入地理解这一概念。

阅读全文 »

0x00 前言

Jenkins是一款使用比较广泛的CI/CD平台,2.0版本开始支持了pipeline,通过jenkinsfile文件进行流水线的控制。本文提供了一种在本地Linux环境中快速搭建Jenkins测试环境的方法。

阅读全文 »

前言

Google Chrome早就支持了headless模式,但一般都是在Linux上运行,而我则习惯于在WSL上开发,折腾了好久终于找到了可以在WSL上跑headless模式的方法。

以下以WSL中安装的是Ubuntu 18.04系统为例。

常见安装方法

安装依赖库

1
$ sudo apt install gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator3-1 libnss3 lsb-release xdg-utils

安装Chrome

1
2
3
4
$ wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
$ sudo dpkg -i google-chrome-stable_current_amd64.deb
$ which google-chrome
/usr/bin/google-chrome

使用Chrome Headless访问网页

使用 官方文档的方法打开Chrome:

1
$ google-chrome --headless --disable-gpu --screenshot https://www.baidu.com/

出现如下报错信息:

1
2
3
Failed to move to new namespace: PID namespaces supported, Network namespace supported, but failed: errno = Permission denied
Failed to generate minidump.Illegal instruction (core dumped)

使用如下命令行也不行:

1
2
3
4
5
6
$ google-chrome --no-sandbox --headless --no-gpu --disable-setuid-sandbox --screenshot http://www.baidu.com/

[0829/140949.035033:WARNING:gpu_process_host.cc(1188)] The GPU process has crashed 1 time(s)
[0829/140950.200613:WARNING:gpu_process_host.cc(1188)] The GPU process has crashed 2 time(s)
[0829/140951.306996:WARNING:gpu_process_host.cc(1188)] The GPU process has crashed 3 time(s)

增加--single-process参数后打印如下信息:

1
2
[0829/141145.431580:ERROR:browser_main_loop.cc(584)] Failed to put Xlib into threaded mode.
[0829/141146.090239:INFO:headless_shell.cc(572)] Written to file screenshot.png.

虽然看起来有报错,但是的确生成网页截图了。

screenshot.png显示如下:

看起来有两个问题:

  • 中文没有正确显示
  • 窗口大小偏小

中文显示的问题可以通过以下命令解决:

1
$ sudo apt install fonts-noto-cjk

修改窗口大小可以通过增加--window-size=1920,1080参数进行修改。

开启远程调试

Headless模式下一般需要通过Chrome远程调试协议进行访问。

命令行增加--remote-debugging-port=9200参数启动Chrome后,打印出以下信息:

1
2
3
4
[0829/194236.072838:ERROR:browser_main_loop.cc(584)] Failed to put Xlib into threaded mode.

DevTools listening on ws://127.0.0.1:9200/devtools/browser/18442c9f-b0ee-4149-a16b-f49622047621
[0829/194236.299565:ERROR:command_buffer_proxy_impl.cc(107)] ContextResult::kTransientFailure: Shared memory region is not valid

看起来调试端口是启动成功了。

但是在访问调试页面后,Chrome进程Crash了。

1
Segmentation fault (core dumped)

试了多个页面后发现,远程调试都会导致Crash,看来这条路不太好走。

使用puppeteer提供的Chrome

无意中发现,puppeteer中提供的Chrome竟然可以在WSL中开启调试端口并正常访问。

puppeteer默认下载地址的格式为:https://storage.googleapis.com/chromium-browser-snapshots/${platform}/${revision}/chrome-${revision}.zip。例如目前Linux上最新版本的URL为:https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/674921/chrome-linux.zip

也可以使用镜像网站下载,例如:https://npm.taobao.org/mirrors/chromium-browser-snapshots/

解压出来就可以直接用了。

总结

  • 安装依赖库,包括中文字体库
  • 使用puppeteer提供的Chrome版本
  • 完整的启动命令行:chrome --no-sandbox --headless --no-gpu --disable-setuid-sandbox --single-process --window-size=1920,1080 --screenshot --remote-debugging-port=9200 http://www.baidu.com/

顺便提供一下puppeteer使用的完整命令行:

1
chrome --disable-background-networking --enable-features=NetworkService,NetworkServiceInProcess --disable-background-timer-throttling --disable-backgrounding-occluded-windows --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-background-pages --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=site-per-process,TranslateUI,BlinkGenPropertyTrees --disable-hang-monitor --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-backgrounding --disable-sync --force-color-profile=srgb --metrics-recording-only --no-first-run --enable-automation --password-store=basic --use-mock-keychain --headless --hide-scrollbars --mute-audio about:blank --no-sandbox --disable-setuid-sandbox --remote-debugging-port=0 --user-data-dir=/tmp/puppeteer_dev_profile-NkEdQ6

0x00 前言

自从有了WSL,在Windows上部署各种服务也变得更加方便。最近,遇到一个问题,本地调试一些Web服务的时候,必须要使用80端口,如果同时有两个服务都监听80端口必然会导致冲突。而且,在Linux中监听80端口需要使用root权限,每次启动的时候都要加上sudo也挺麻烦的。

因此,想到可以利用nginx的反向代理能力,在本地进行HTTP的转发,这样,每个服务就可以使用自己的端口了。

阅读全文 »

0x00 问题描述

今天在Win10上遇到一个很诡异的问题,使用python3的virtualenv创建虚拟环境失败,报错如下:

1
2
3
4
5
6
7
Using base prefix 'c:\\users\\xxx\\appdata\\local\\programs\\python\\python37'
New python executable in D:\env\Scripts\python3.exe
Also creating executable in D:\env\Scripts\python.exe
ERROR: The executable D:\env\Scripts\python3.exe is not functioning
ERROR: It thinks sys.prefix is 'd:\\' (should be 'd:\\env')
ERROR: virtualenv is not compatible with this system or executable
Note: some Windows users have reported this error when they installed Python for "Only this user" or have multiple versions of Python installed. Copying the appropriate PythonXX.dll to the virtualenv Scripts/ directory may fix this problem.

同时还会有如下弹窗:

定位原因

根据错误信息在网上寻找解决方法,有说是pythonxx.dll有问题,还有说是权限问题,但试了下都没法解决这个问题。因此,只能尝试在本地寻找复现规律。

发现将python3.exe复制到其它路径后都无法运行,报错与创建虚拟环境一致;而在另一台Win10机器上却没有这个问题。所以,看来原因应该是python环境有问题,但为什么默认路径运行却是正常的呢?

一开始以为是python37.dll的问题,但是很快又排除了。此时,发现python3安装目录下有个vcruntime140.dll文件,而这个文件是不会被复制到虚拟环境中的,难道是这个dll的问题?

将这个dll拷贝到虚拟环境目录后,果然python可以正常运行了。

因此确定,就是vcruntime140.dll这个文件的锅了。

终极解决方案

但是其它Win10上没有拷贝这个dll,也是正常的啊。所以,还需要进一步寻找原因。

接着,将正常电脑上python安装目录里的vcruntime140.dll文件删掉,运行python,也是正常的。使用procexp查看加载的dll,发现原来python会从C:\Windows\system32目录下加载该dll。

在有问题的电脑上看了下该目录,文件也是存在的啊,那是怎么回事呢?

右键查看文件属性,终于发现了根本原因,原来文件的权限设置有问题,估计这个dll是在入域前装上去的,导致只能在管理员权限下访问。

修改文件权限后,一切都正常了。

总结

根据程序的报错信息不一定能正确地找到解决问题的方法,有时还是需要进一步跟踪调试,才能找到问题的真正原因。