改坏了 sudo 的配置文件, 又没有办法切换到 root 用户? 也许 polkit 能救你!

今天帮基友折腾 Ubuntu 的时候, 修改 /etc/sudoers 不小心改坏了格式, 然后 sudo 提示 sudoers 格式不对无法运行, 然后各种泪目. 突然想到 polkit 直接调用 systemd (或者在较老的系统上调用 consolekit), 或许可以绕过 sudo 提权. 于是在终端敲下了:

$ pkexec bash

输入密码后果断进入了 root shell! 于是省去了一次重启改 init 然后 remount (或者插入安装盘 mount 等)的繁琐步骤…

希望可以帮到谁 XD

[Arch] 今日更新的 fcitx(-gtk2) 在 gtk2 应用中无法使用问题的解决与启示

今日更新了 fcitx, 许多用户反馈在部分应用程序中无法激活/使用, 虽然这类问题已经并不新鲜, 但是我觉得还是有必要说明一下.

首先, 这个问题从根本上是pacman的错(升级顺序混乱).

升级的时候你应该看到 fcitx-gtk2/fcitx-gtk3 的 installing 后面跟着个 error, 那就是因为, 存在下面的依赖链(以 fcitx-gtk2 为例):

fcitx-gtk2 -> gtk2 -> pango -> harfbuzz -> icu

最后的两个都在升级列表里, 而按照逻辑, fcitx-gtk2 需要在他们之后升级才是正常的, 但是 pacman 没有考虑这个问题(依赖链中间有两个未参与此次升级的包).

我今天中午收到反馈就 bump 了版本(在基友 yuyichao 的建议下更新了 fcitx-gtk2.install, 简单的 hack 了一下使得以后类似情况时不出现此问题), 现在你看到(或者装了)的应该是 -3 结尾的版本号. 但是即使升级后, 所有使用 gtk2 相关库的应用程序仍需重启才能生效.

因为类似情况并不是第一次出现了(以前有数次大规模 rebuild 后某些包不正常的情况), 基本上如果你在升级过程中看到有库链接错误/segfault/参数错误之类的提示, 在此次升级指令完成后把这些出错的包重新安装, 如果还有错, 继续安装有错的包直到没有错为止. 这样基本上可以解决大部分的此类问题.

另附此次我机子上 fcitx-gtk* 升级出错的 log 以便大家参考前文的分析 (无关包已去掉)

[2012-11-17 10:58] upgraded icu (49.1.2-2 -> 50.1-2)
[2012-11-17 10:58] upgraded fcitx (4.2.6.1-1 -> 4.2.6.1-2)
[2012-11-17 10:58] usr/bin/gtk-query-immodules-2.0: error while loading shared libraries: libicule.so.49: cannot open shared object file: No such file or directory
[2012-11-17 10:58] upgraded fcitx-gtk2 (4.2.6.1-1 -> 4.2.6.1-2)
[2012-11-17 10:58] usr/bin/gtk-query-immodules-3.0: error while loading shared libraries: libicule.so.49: cannot open shared object file: No such file or directory
[2012-11-17 10:58] upgraded fcitx-gtk3 (4.2.6.1-1 -> 4.2.6.1-2)
[2012-11-17 10:58] upgraded qt (4.8.3-5 -> 4.8.3-6)
[2012-11-17 10:58] upgraded fcitx-qt (4.2.6.1-1 -> 4.2.6.1-2)
[2012-11-17 10:58] upgraded harfbuzz (0.9.5-1 -> 0.9.5-2)

一句话检查自己 Arch 里装的 AUR 包是否和社区同步

我们知道 aurget yaourt 等工具可以解决普通升级的情况, 但是如果一个包改名了, 或者(不靠谱的)维护者降级了没加前置version, 这些工具不会给出任何提示. 如果没有关注自己使用的包的 comments (没有notify) 以及 aur-general 邮件列表的话, 常常会错过这样的信息, 以致自己机子上的包过期很久也没发现, 以后出现莫名其妙的问题什么的(

举例来说, aur/qtcreator-bin 被收入 [community] 一段时间了, 因为收入后改了名 (新名称是 qtcreator), 导致 yaourt 没有给我任何提示. 今天用下面的语句检查后我才发现, 自己机子里的 qtcreator-bin (版本2.3) 包已经不在 AUR 里了, 而[community-testing]/qtcreator 版本是2.6.0beta, 可见我这里的包已经过期许久.

和上次的小脚本一样, 我又用到了 GNU Parallel, 嗯就是这样(

pacman -Qmq | parallel 'ver=($(package-query {} -AQ -f "%l")); [[ "${ver[0]}" != "${ver[1]}" ]] && echo {} ${ver[0]} != ${ver[1]}'

记一次虚拟机装 FreeBSD 9 #坑爹

嗯还是忍不住把 #坑爹 放在了标题里, 这个…嗯有槽请轻吐什么的我才不知道呢(

虚拟机是 VirtualBox OSE 的最新版. (才不告诉你们为什么用OSE

首先呢, 作为一个 Arch 用户, 俺打开 FreeBSD 的网站看到 8.3 和 9.0 乃说我会下哪个呢? (喂喂

然后… 安装光盘引导到一半… 神马? mount 光驱 失败??!!

经过一番用力的Google总算找到了 这个帖子 , 原来是Chipset选的不对啊..喂喂VirtualBox乃都为每个操作系统改一些Presets了为啥不干脆把FreeBSD默认到ICH系列啊??!!

然后… 基本用默认配置连分区都没改安装到 ports, 挂了, 提示 out of inodes.

于是S&L大法启动, 重新引导安装进到分区修改界面按编辑… なに? 居然没有输入自定义选项的地方, 上网随手一搜大家的方法都坑爆了, 比如装到一半挂了重引导用dd还有什么一番折腾然后再手动完成剩下的安装过程(

后来呢… 后来还是找到对头的地方了, 这个帖子这个Issue 报告, 然后告诉我在9.1修了…

于是… 于是果然还是重新下了一个9.1的iso装上了嗯! (

然后心血来潮想装 virtualbox 的 guest additions (虽然现在想想不知道为什么以及有什么用 = =

然后按官网给的方法要自己make install, 然后告诉我没装src, 哦对确实没装src… 然后… 神马? “要装src请自己下载然后解压到/”, 喂喂这不是坑爹么在这guest里没有curl也没有wget好吧我不知道其他可能有的下东西的命令了 (

于是只好用给的另外一个方法(csup) 装上了src, 然后make install 到一半… 果然磁盘空间没了… df一看剩余空间居然是..负…的…..(超神了有木有!!

好吧VirtualBox我选FreeBSD乃建磁盘时默认给填容量2G啊坑我幸亏我看到安装光盘都不止2G(嘻嘻看我聪明吧)于是我给了4G然后果然… 还!!是!!不!!够!!啊!!!!!!!

于是… 从头再来装在一个8G的上面, 嗯这次总算靠谱了, 不过截止现场的消息, 从今天早上make install 到晚上11点, 目前仍然没有编译完依赖 (zZ2…

嗯没了 (喂喂这流水帐有点过分啊!

简单的 Arch 第三方软件源自动化同步上传工具

首先解释下, 这玩意是给包维护者用的, 不是给普通用户的(
功能: 扫描自己维护的包列表, 同步所有包到远程软件仓库. 自动判断architecture. 如使用 yaourt, 需要配置 yaourt 输出到 pacman 目录, 或者手动修改工具里的路径.
PKGLIST格式: 一行一个包名.
PS: 因为用到了 GNU Parallel, 所以记得装一下嗯(

packageupload:

#!/bin/bash
[[ "$1" = *x86_64* ]] && ARCH=x86_64 || ARCH=any
echo "Uploading $1 to repo, architecture: $ARCH"
rsync -azP $1 root@$SERVER_IP:/home/www/repo/$ARCH/

packagesync:

#!/bin/bash
cat /path/to/PKGLIST|xargs pacman -Q|sed -e "s/\\s/-/"|xargs -IQ bash -c "ls /var/cache/pacman/pkg/Q-*"|parallel packageupload

计算SMSC的方法 (附带Py小工具)

早上小青蛙 @hexchain 发不了短信找俺要SMSC号码, 于是…嗯…
于是…步骤就用代码里的注释描述算了, 直接上代码:

#!/usr/bin/env python2
#coding:utf-8
import sys

# 获取短信中心号码
if len(sys.argv) > 1:
    orig = sys.argv[1]
else:
    print "输入短信中心号码:",
    orig = raw_input()
    
# 去掉+号
if orig[0] == "+":
    orig = orig[1:]

# 不是偶数在后面加F
if len(orig) % 2 == 1:
    orig = orig + "F"

# 把奇位和偶位互换
orig = "".join(["".join(x) for x in zip(orig[1::2],orig[::2])])

# 在号码前加91(国际化)+字符长度/2
orig = "91" + orig
orig = "%02d" % (len(orig)/2) + orig

print orig

参考资料: http://read.pudn.com/downloads179/sourcecode/embed/835292/new/SMSTABLE.h__.htm

Archlinux – 安装 testing/glibc 2.16.0-2 时出现 “/lib exists in filesystem” 的一种处理方法

首先感谢falconindy提供的几个note, 这是我的解决思路的基础:

A few things to note...

1) If you find yourself in a position to recreate the symlink yourself, the link target is [b]usr/lib[/b] and not [b]/usr/lib[/b]. This is an important difference that's only evident in a chroot situation.
2) The linker is an interpreter, just like /bin/bash. If it exists on the system but the /lib symlink is missing/fubar, you can run ELF binaries directly via the linker, e.g. /usr/lib/ld-2.16.so /bin/ln -s ....

我遇到了和litemotiv一样的问题:
清理过/lib, 保证里面的文件都属于 glibc 后再次尝试升级:

(1/2) upgrading glibc                                                                            [########################################################] 100%
error: extract: not overwriting dir with file lib
error: problem occurred while upgrading glibc
call to execv failed (No such file or directory)
error: command failed to execute correctly
error: could not commit transaction
error: failed to commit transaction (transaction aborted)
Errors occurred, no packages were upgraded.

我的问题的特殊点是: 我没有打开一个root权限的命令行, root密码登陆被禁用(所以我无法使用su root), 而且我无法使用上面说的ld-2.16.so去加载sudo(由于sudo本身的安全规则).

于是我琢磨出了下面的方法去修复这个已经挂掉的系统, 希望能帮到遇到类似问题的盆友:

  1. 重启, 编辑grub里linux(或kernel)开头的那行, 在尾部添加:
    init=/usr/lib/ld-2.16.so /bin/sh
  2. remount文件系统使其可写:
    /usr/lib/ld-2.16.so /bin/mount -o remount,rw /
  3. 移除空的(上面的错误会使它是空的) /lib 目录:
    /usr/lib/ld-2.16.so /bin/rmdir /lib
  4. 手动修复链接:
    /usr/lib/ld-2.16.so /bin/ln -s usr/lib /lib
  5. 按 ctrl-alt-del 重启电脑, 然后用pacman重新安装一次glibc

然后各种东西都恢复正常了, 不需要使用恢复光盘之类的东西 🙂

参考: https://bbs.archlinux.org/viewtopic.php?pid=1126667#p1126667

给 Systemd 的操作加上 Bash 简写及其自动完成

大家都知道 systemd 启个服务打 systemctl start nginx.service 实在是长的难受(尽管有Tab…), 于是 ArchWiki 上有介绍一个简单用 start nginx 来代替的方法, 但是这个方法没有 Bash 自动补全, 于是我自己折腾了一下..

补全函数都取自他们各自原来的 bash-completion 文件, 我只修改了一点点(可惜不能复用啊..).

嗯, 照例上代码…
/etc/bash.bashrc, 或者 ~/.bashrc 里添加:

if ! systemd-notify --booted; then  # not using systemd
  start() {
    sudo rc.d start $1
  }

  restart() {
    sudo rc.d restart $1
  }

  stop() {
    sudo rc.d stop $1
  }
else
  _target() {
    if [[ "$1" == *.service ]]
    then
      echo $1
    else
      echo $1.service
    fi
  }
  export -f _target

  start() {
    sudo systemctl start $(_target $1)
  }
  export -f start

  restart() {
    sudo systemctl restart $(_target $1)
  }
  export -f restart

  stop() {
    sudo systemctl stop $(_target $1)
  }
  export -f stop

  enable() {
    sudo systemctl enable $(_target $1)
  }
  export -f enable

  status() {
    sudo systemctl status $(_target $1)
  }
  export -f status

  disable() {
    sudo systemctl disable $(_target $1)
  }
  export -f disable
fi
Continue reading 给 Systemd 的操作加上 Bash 简写及其自动完成

简易的默认网关保存+Bash补全解决方案 For Arch Linux

嗯, 本猫的脚本有多烂大大们都知道的, 所以本文旨在抛砖引玉, 简单介绍利用 pppd hook 和 dhcpcd hook 做到记忆网关, 以及 bash_completion 补全的实现.

保存用的脚本:
/usr/local/bin/froute-save

#!/bin/bash
interface=${interface:-$1}
gateway=${new_routers:-$5}

if [ "$reason" = 'BOUND' ] && ! ([ -z "$interface" ] || [ -z "$gateway" ])
then
    mkdir -p /tmp/froute/
    chmod 755 /tmp/froute
    echo $gateway > /tmp/froute/$interface
    chmod 644 /tmp/froute/$interface
elif ([ "$reason" = 'STOP' ] || [ "$reason" = 'RELEASE' ]) && ! [ -z "$interface
" ]
then
    rm -f /tmp/froute/$interface
fi

嗯..然后首先是pppd的hook, 代码如下:
/etc/ppp/ip-up.d/02-route.sh

reason=BOUND froute-save $1 0 0 0 $5

/etc/ppp/ip-down.d/02-route.sh

reason=RELEASE froute-save $1

然后是dhcpcd的hook.
/etc/dhcpcd.enter-hook

froute-save

如果有用 netcfg 设置静态地址连接, 可以参考如下配置:

POST_UP="env reason=BOUND froute-save $INTERFACE 0 0 0 $GATEWAY || true"
PRE_DOWN="env reason=RELEASE froute-save $INTERFACE || true"

嗯, 现在记忆网关的部分就完成了 ><

Continue reading 简易的默认网关保存+Bash补全解决方案 For Arch Linux

检查 /usr 目录哪些文件不在包管理里 For Arch Linux

当然改改里面的命令也就能用在其他发行版了= =
随手写的, 各种不靠谱勿喷哦><

#!/usr/bin/env python2
import subprocess
import os
from os.path import join

pkg_list = subprocess.check_output(["pacman", "-Q"]).split("\n")[:-1]
pkg_list = map(lambda line:line.split()[0], pkg_list)

file_mapper = {}
for pkg in pkg_list:
    file_list = subprocess.check_output(["pacman", "-Ql", pkg]).split("\n")[:-1]
    file_list = map(lambda line:line.split(" ",1)[1], file_list)
    for filename in file_list:
        file_mapper[filename] = pkg

for root, dirs, files in os.walk('/usr'):
    if "__pycache__" in root:
        continue
    for name in files:
        filename = os.path.join(root, name)
        if filename not in file_mapper:
            if filename.endswith(".pyc") or filename.endswith(".cache"):
                continue
            print filename, "Not Found!"
QR Code Business Card