分类: linux

  • Linux 命令行笔记

    遍历目录查找内容

    grep -rnw '/path/to/somewhere/' -e 'pattern'
    • -r 或 -R 表示遍历
    • -n 显示行号
    • -w 全文匹配
    • -l (小写 L) 只显示文件名
    • -e 匹配的表达式

    参考:How do I find all files containing specific text on Linux? – Stack Overflow

    复制多个目录

    cp -r d1 d2 d-* dist/

    查找磁盘占用

    ubuntu@VM-16-15-ubuntu:~$ sudo du -h --max-depth=1 /var/lib/docker/volumes | sort -h
    8.0K	/var/lib/docker/volumes/7e6264b4649948452587e6b562dae6a5881d17ba0254eefb6a98e32dae35f593
    8.0K	/var/lib/docker/volumes/e3a990377c6c214dd7b8c45807c8f63319988b2a29c4e58d13c0445da3e2e7d5
    8.0K	/var/lib/docker/volumes/sentry-self-hosted_sentry-kafka-log
    8.0K	/var/lib/docker/volumes/sentry-self-hosted_sentry-secrets
    12K	/var/lib/docker/volumes/373a3159029b89230c64a7dc74633a48f29fa5a10dd7fee57a16318d659e76a7
    12K	/var/lib/docker/volumes/sentry-self-hosted_sentry-smtp-log
    28K	/var/lib/docker/volumes/sentry-self-hosted_sentry-nginx-cache
    36K	/var/lib/docker/volumes/sentry-symbolicator
    92K	/var/lib/docker/volumes/sentry-self-hosted_sentry-smtp
    144K	/var/lib/docker/volumes/sentry-self-hosted_sentry-zookeeper-log
    368K	/var/lib/docker/volumes/sentry-zookeeper
    712K	/var/lib/docker/volumes/sentry-data
    1.8M	/var/lib/docker/volumes/sentry-redis
    814M	/var/lib/docker/volumes/sentry-self-hosted_sentry-clickhouse-log
    1.6G	/var/lib/docker/volumes/sentry-clickhouse
    14G	/var/lib/docker/volumes/sentry-postgres
    16G	/var/lib/docker/volumes/sentry-kafka
    31G	/var/lib/docker/volumes
    
  • 在 Fedora 34 上启动 VNC DISPLAY

    在 Fedora 34 上启动 VNC DISPLAY

    大家可以先阅读 使用 Node.js 驱动 FFmpeg 在 Linux + vncserver 下完成视频录制 了解产品目标和技术选型。

    前两天在系统更新里看到 Fedora 34 发布,作为更新党,我当然迫不及待就升级了。升级过程蛮顺利的,升级后,系统里的“在线账户”也能正常走 VPN 了,感觉还蛮好的。

    然后,前两天需要调试录视频的程序,发现新系统的 tigerVNC 有一个巨大的变化:不再支持用 vncserver 命令创建虚拟显示器,必须用 systemctl start service,目的是方便绑定系统启动,因为很多服务器的运维需要自动化。

    不过这可苦了我。我是系统运维菜鸡,基本只能照抄文章,搞了半天也没搞好。不过感谢开源,在 GitHub issue 里讨论的只言片语让我知道了其实 vncserver 是个脚本,它调用的其实是 Xvnc 这个命令。

    那就好办了,我开始按图索骥,寻找 vncserverXvnc 之间的关联。最终找到解决方法如下:

    1. 修改 /etc/X11/Xwrapper.config,加入 allowed_users=anybody。这样才能直接使用 Xvnc 创建虚拟显示器,不然会报告只有 console 用户才能创建的错误。
    2. 使用 vncpasswd 命令创建密码文件,创建后的密码文件位于 ~/.vnc/passwd
    3. 然后用 Xvnc :5 -geometry 1280x720 -PasswordFile ~/.vnc/passwd 创建显示器,跟之前的命令很类似,不过需要 -PasswordFile 选项指定密码
    4. 使用 VNC viewer 登录 VNC,输入密码。(我不知道这一步是否必须)
    5. 可以继续使用 DISPLAY=:5

    不过问题并没有完美解决,虽然我的 puppeteer JS 能跑,FFmpeg 也能录。但是 DISPLAY=:5 firefox https://cn.bing.com 只会在当前屏幕打开窗口,不知道为什么。留待以后解决吧。

    最后吐槽下,这种稳定版里换大版本的行为真的要不得,开源团队也不能滥用自己的地位。


    参考阅读

  • Linux 命令行科学上网

    Linux 命令行科学上网

    前些天因为工作需要,装了 Fedora 33 开发 Showman 的视频录制功能。准备顺势双机工作一段时间,自然也就需要给新系统配置好科学上网。这里简单记录一下过程,方便日后回查。

    0. 更新系统

    第一部当然是更新系统,保证系统组件均为最新版,这样可以规避大多数问题。

    sudo dnf update

    1. 使用 pip 安装 shadowsocks 客户端

    Fedora 33 自带 python 3.9,所以直接使用 pip 安装 shadowsocks 客户端即可:

    sudo pip install shadowsocks

    这里可以用 sudo 也可以不用,差别就在于,sudo 之后会将执行脚本安装到 /usr/local/bin;而不带 sudo 则会安装到 ~/.local/bin。两者的执行环境不一样。我无意间使用了后者,所以后面也会按照后者来记录。

    2. 配置客户端

    接下来编辑配置文件,如果是图形界面,建议使用 IDE,纯命令行的话用 vim 也可以。配置文件一般放在 /etc/shadowsocks.json。内容大概如下,顾名思义,我就不一一解释了:

    {
      "server":"server-ip",
      "server_port":8000,
      "local_address": "127.0.0.1",
      "local_port":1080,
      "password":"your-password",
      "timeout":600,
      "method":"aes-256-cfb"
    }

    与前面 Ubuntu 20.04 科学上网 一样,本文不打算介绍服务器的制备——其实我也不建议大家自己制备服务器,除非你本来就有一些资源或者需求。不然的话,以我的经验,比较出名的迷你 VPS(类似 Vultr,DO,$5/月甚至 $2.5/月),IP 大部分都在规则库里,流量大一点,比如看个视频,不出半个小时 IP 就被封了,然后一个月后解封,基本没法用。

    如果你是 macOS 或者 iPhone,或者其它支持 AnyConnect 的系统,可以考虑直接买现成的,比如链接里这个

    3. 配置系统代理

    然后启动服务:

    sslocal -c /etc/shadowsocks.json -d start
    • -c 用来指定配置文件的地址
    • -d 表示启动服务

    这里可能会遇到几个问题(也是上次我放弃命令行转投 qt5 客户端的原因)。我们来逐个解决它们:

    3.1 openssl 错误

    执行后报错:

    $ sslocal -c /etc/shadowsocks.json -d start
    INFO: loading config from /etc/shadowsocks.json
     2021-05-05 15:17:00 INFO     loading libcrypto from /root/anaconda3/lib/libcrypto.so.1.1
     Traceback (most recent call last):
       File "/root/anaconda3/bin/sslocal", line 8, in <module>
         sys.exit(main())
       File "/root/anaconda3/lib/python3.9/site-packages/shadowsocks/local.py", line 39, in main
         config = shell.get_config(True)
       File "/root/anaconda3/lib/python3.9/site-packages/shadowsocks/shell.py", line 262, in get_config
         check_config(config, is_local)
       File "/root/anaconda3/lib/python3.9/site-packages/shadowsocks/shell.py", line 124, in check_config
         encrypt.try_cipher(config['password'], config['method'])
       File "/root/anaconda3/lib/python3.9/site-packages/shadowsocks/encrypt.py", line 44, in try_cipher
         Encryptor(key, method)
       File "/root/anaconda3/lib/python3.9/site-packages/shadowsocks/encrypt.py", line 82, in __init__
         self.cipher = self.get_cipher(key, method, 1,
       File "/root/anaconda3/lib/python3.9/site-packages/shadowsocks/encrypt.py", line 109, in get_cipher
         return m[2](method, key, iv, op)
       File "/root/anaconda3/lib/python3.9/site-packages/shadowsocks/crypto/openssl.py", line 76, in __init__
         load_openssl()
       File "/root/anaconda3/lib/python3.9/site-packages/shadowsocks/crypto/openssl.py", line 52, in load_openssl
         libcrypto.EVP_CIPHER_CTX_cleanup.argtypes = (c_void_p,)
       File "/root/anaconda3/lib/python3.9/ctypes/__init__.py", line 395, in __getattr__
         func = self.__getitem__(name)
       File "/root/anaconda3/lib/python3.9/ctypes/__init__.py", line 400, in __getitem__
         func = self._FuncPtr((name_or_ordinal, self))
     AttributeError: /root/anaconda3/lib/python3.9/lib-dynload/../../libcrypto.so.1.1: undefined symbol: EVP_CIPHER_CTX_cleanup

    其中文件、行号可能有所不同,不过错误内容大多一致。

    这是因为 OpenSSL 升级至 1.1.0 以上后,内部 API 有一些变化,废弃了 EVP_CIPHER_CTX_cleanup() 函数而引入了 EVE_CIPHER_CTX_reset(),shadowsocks 客户端处于无人维护的状态,没有适配这些变化。

    好在修复方案并不复杂,我们只需要修改文件 ~/.local/lib/python3.9/site-packages/shadowsocks/crypto/openssl.py,将里面的 cleanup 都替换成 reset 即可。

    3.2 permission denied /var/run/shadowsocks.pid

    前面写过,因为我安装的时候没使用 sudo,所以把客户端装在当前用户的目录里。于是面临一个矛盾:

    1. 直接使用当前用户启动客户端,会报告标题里的错误
    2. 使用 root 即 sudo 启动客户端,会报告库有错误(即 3.1),因为我修改的是当前用户的本地库

    这里有两个解决方案,一是手动创建 pid,然后修改权限:

    sudo touch /var/run/shadowsocks.pid
    sudo chmod 777 /var/run/shadowsocks.pid

    这个方法重启后会失效,还得再跑一遍。所以我比较推荐另一种做法:使用 sudo -u $user -i 的方式,sudo 的同时仍然使用当前用户的环境(这个方案实测失败了,还要再研究下):

    sudo -u meathill -i sslocal -c /etc/shadowsocks.json -d start

    4. 加入自动启动

    上一步测试成功之后就可以把这段代码加入 /etc/rc.local,以便实现开机自动启动。

    5. 其它步骤

    接下来,需要配置 pac 文件、文件服务和系统代理,可以完全参考 Ubuntu 20.04 科学上网 一文。

    其中下载 gfwlist.txt 时,如果访问不到 https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt,可以试着修改 /etc/hosts,加入下一行:

    199.232.28.133 raw.githubusercontent.com

    完成剩余步骤后,配置成功。


    在 macOS/iOS 设备上使用科学上网有更简单的方法,扫码可得(其实只要你有 AnyConnect,并不限制系统平台):

  • 解决 WSL Ubuntu 20.04 下使用 apt 源安装 node.js 的问题

    解决 WSL Ubuntu 20.04 下使用 apt 源安装 node.js 的问题

    随着 Ubuntu 20.04 发布,各大平台都适配发布了对应版本的系统,Windows WSL 也不例外。如果你是新系统,直接在 Microsoft Store 里搜索并安装 Ubuntu 即可;如果你是老系统,已经装过以前的版本,那么需要先卸载再安装,如果直接安装 Ubuntu 20.04 会有多个不同版本的 Ubuntu 共存。

    装完系统后,接着安装其它软件。我现在比较喜欢用包管理工具安装软件,因为容易更新,而我又是更新爱好者。所以按图索骥,找到 node.js 的二进制包安装指引,复制执行:curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash - ,结果报错:gpg: can't connect to the agent: IPC connect call failed

    经过搜索,得知这是 WSL 版 Ubuntu 20.04 的问题,与 WSL1 有一些不兼容,在 WSL2 上就没这个问题了。解决方案是装一些工具:

    sudo add-apt-repository ppa:rafaeldtinoco/lp1871129
    sudo apt update
    sudo apt install libc6=2.31-0ubuntu8+lp1871129~1 libc6-dev=2.31-0ubuntu8+lp1871129~1 libc-dev-bin=2.31-0ubuntu8+lp1871129~1 -y --allow-downgrades
    sudo apt-mark hold libc6

    然后问题就解决了。

    这个 issue 里还记录了一些别的方案,包括上面方案的修正版,不过我用起来没问题,也就没继续往下看。感兴趣的同学可以研究一下。

  • 解决 Ubuntu 20.04 下无法打开蓝牙的问题

    解决 Ubuntu 20.04 下无法打开蓝牙的问题

    我的 Ubuntu 20.04 启动之后经常丢掉蓝牙。表现是设置里能看到蓝牙,状态是关闭,但是无法打开,每次点击开关过一会儿就恢复了,也没有报错。

    因为要连接音箱,没有蓝牙很不方便,就搜索了一下,最后发现下面的解决方案。虽然没理解问题根源,但是解决了就好。

    sudo rmmod btusb
    sleep 1
    sudo modprobe btusb

    参考链接:

    1. Bluetooth firmware upload failing after ‘suspend’
    2. Bluetooth used to be enabled, now disabled and won’t enable. Ubuntu 16.04
  • 重置 MariaDB root 密码

    重置 MariaDB root 密码

    以我最常用的 Ubuntu 为例,记录如何重置 MariaDB root 密码。MariaDB 是 MySQL 原作者在 MySQL 闭源之后的再起之作,基本能完全兼容 MySQL。在我的 Ubuntu 上,它的大部分命名都沿用 MySQL。

    1. 停掉 mysql 服务

    $ service mysql stop

    2. 以特殊方式启动 mysql

    使用 --skip-grant-tables 可以跳过用户权限检查,让你没有密码也能连接。此时为了避免安全问题,可以加上 --skip-networking,防止有人此时通过网络连接你的数据库。在本地环境下差别不大。

    $ sudo mysqld_safe --skip-grant-tables --skip-networking &

    这一步可能会启动失败,导致下一步连接时报错:ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ’/var/run/mysqld/mysqld.sock’ (2),此时,可以这样修正:

    $ sudo mkdir /var/run/mysqld
    $ sudo chown mysql /var/run/mysqld

    3. 连接数据库

    $ mysql -u root

    正常情况下就连上了。

    4. 重置密码

    mysql> FLUSH PRIVILEGES;
    mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password';

    5. 重启 mysql

    按照参考文档里介绍的做法,需要

    $ sudo kill `cat /var/run/mysqld/mysqld.pid`
    # 或
    $ sudo kill `/var/run/mariadb/mariadb.pid`

    不过我实际操作的时候只要把(2)开启的进程关掉就好了。然后重启 mysql 服务:

    $ service mysql restart

    6. 完成

    尝试一下连接,应该可以成功了:

    $ mysql -uroot -p

    7. Ghost 连接

    虽然命令行连接成功,但是 ghost start 仍然报错,经查,是 Ghost 的数据库连接方式有点问题,修改 config.production.json,加入一行配置即可,大体如下:

    {
      "client": "mysql",
      "connection": {
        ....
        "socketPath": "/var/run/mysqld/mysqld.sock",
      }
    }
    (更多…)
  • Ubuntu 20.04 科学上网

    Ubuntu 20.04 科学上网

    闲言少叙,直奔主题。

    0. 服务器

    首先,你得先准备个服务器。本文不讨论如何制备科学上网服务器。

    如果你用 Mac 或者 iPhone,想玩 Clubhouse,可以考虑买个现成,比如链接里这个(其实只要你有 AnyConnect,任何系统都可以用)。

    1. 客户端

    接下来,下载客户端。

    我用的是 shadowsocks-qt5,先在 https://github.com/shadowsocks/shadowsocks-qt5/releases 这个页面下载打包好的 AppImage 文件。

    右键点击文件,在“权限”选项卡里勾选“允许文件作为程序执行”,然后双击运行,配置服务器信息。配置完成,点击“连接”,顺利的话,就会显示连接成功。

    在命令行里输入 gnome-session-properties,会启动如下图所示的“启动应用程序首选项”,把刚才下载的 AppImage 路径添加进来,这样每次启动 ss 客户端都会自动启动了。

    启动应用程序首选项

    2. 生成 pac

    安装genpac

    pip install genpac

    Ubuntu 20.04 默认 python版本是 3,所以可以使用 pip3 替代上面的 pip。

    使用在线的 gfwlist

    genpac --pac-proxy "SOCKS5 127.0.0.1:1080" --gfwlist-proxy="SOCKS5 127.0.0.1:1080" --gfwlist-url=https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt --output="autoproxy.pac"

    使用离线的 gfwlist

    如果你的机器没有完成配置,暂时无法访问到 gfwlist,也可以先想办法下载到这个文件,然后离线生成。

    genpac --pac-proxy "SOCKS5 127.0.0.1:1080" --gfwlist-proxy="SOCKS5 127.0.0.1:1080" --gfwlist-local=你的路径/gfwlist.txt --output="autoproxy.pac"

    3. 配置服务器

    Ubuntu 安装时就集成了 Apache2,并且默认也会启动它,所以直接把刚才生成的 pac 文件放在 /var/www/html/ 目录下,就能通过 http://localhost/autoproxy.pac 访问到。

    不过我不喜欢用 apache,一般都会用 nginx 或者 openresty 取代之。好在默认情况下,nginx 的 web 服务目录也是 /var/www/html,所以只要卸载 apache 然后重新安装 nginx 即可。另外因为这个服务只为使用 pac 文件,所以可以不用换源。

    sudo apt remove apache2
    sudo apt update
    # 安装 openresty 需要的系统依赖
    sudo apt-get -y install --no-install-recommends wget gnupg ca-certificates
    # 添加 key
    wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add -
    # 添加 openresty 官方源
    echo "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main" 
        | sudo tee /etc/apt/sources.list.d/openresty.list
    # 在更新一次,然后安装
    sudo apt update
    sudo apt install openresty
    sudo service openresty start

    然后访问 http://localhost/autoproxy.pac,如果能打开,就说明配置成功。

    4. 启动全局配置

    如果,打开“设置”,找到“网络”,打开“网络代理”,选择“自动”,然后填入上面说的 pac 地址即可。

    5. 在其它应用里完成配置

    比如,打开 Firefox,在“首选项”里找到“网络设置”,然后选择“使用系统代理设置”即可。

    (更多…)