你需要一個基本的 mail server 來處理一些系統上的通知信件,但是又不想裝上複雜的 postfix 或 sendmail. 這時可以用 nullmailer,它的功能十分簡單陽春,不聽 port 25, 連基本的 newaliases 都沒有。
設定檔就 10 個,每個設定檔只有一行。

control file used by
adminaddr nullmailer-queue
defaultdomain nullmailer-inject
defaulthost nullmailer-inject
helohost nullmailer-send
idhost nullmailer-inject
me nullmailer-inject
pausetime nullmailer-send
remotes nullmailer-send
sendtimeout nullmailer-send

基本上,最重要的是 remotes,讓你設定 smarthost 位址。支援的 smarthost protocols 有 smtp, qmqp。常見的 smtp 也支援 SSL,以 gmail 為例子,你可以這樣設定

cat > /etc/nullmailer/remotes
smtp.gmail.com smtp --port=587 --starttls --[email protected] --pass=password

你也可以透過 dpkg-reconfigure nullmailer 來設定。其他的 smtp 參數有

/usr/lib/nullmailer/smtp -h
usage: smtp [flags] remote-address < mail-file
Send an email message via SMTP
-p, --port=INT Set the port number on the remote host to connect to
--user=VALUE Set the user name for authentication
--pass=VALUE Set the password for authentication
-d, --daemon use syslog exclusively
-s, --syslog use syslog additionally
--auth-login Use AUTH LOGIN instead of auto-detecting in SMTP
--ssl Connect using SSL (on an alternate port by default)
--starttls Use STARTTLS command
--x509certfile=VALUE Client certificate file
--x509cafile=VALUE Certificate authority trust file
(Defaults to /etc/ssl/certs/ca-certificates.crt)
--x509crlfile=VALUE Certificate revocation list file
--x509fmtder X.509 files are in DER format
(Defaults to PEM format)
--insecure Don't abort if server certificate fails validation

-h, --help Display this help and exit

(以上指令測試於 Ubuntu 13.04, raring)

經過幾年發展,DBus 已經取代早年 Linux 桌面環境所用的 GNOME Bonobo, KDE DCOP,用於許多應用程式,成為主流 IPC 系統。隨著軟體原件逐漸成熟,眾多程式語言都已經支援 DBus APIs,DBus daemon 的 footprint 也逐漸能夠被嵌入式所接受,而被行動裝置作業系統如 MeeGo, WebOS 所採用。

Linux 開發者難免因爲介接需求,需要測試或使用 DBus 除錯。這裡分享幾個常用的小技巧。DBus 使用物件導向的 API 界面,所有 ServicesObject 函式都是以 Method, Signals, Properties 的概念揭露給外界存取,配合 Introspectable API,很容易讓第三方介接。

最常用到的工具之一是 dbus-send,它可以用來從指令列測試接傳 DBus messages,像是列出系統上所有註冊在 Session BusServices

$ dbus-send --session --print-reply --reply-timeout=2000 \
--type=method_call --dest=org.freedesktop.DBus /org/freedesktop/DBus  \
org.freedesktop.DBus.ListActivatableNames

有了 Services 名稱,接下來你就可以用 Service 為名以 Introspection 界面去查詢其所開放之 API,如

$ dbus-send --session --print-reply --reply-timeout=2000 --type=method_call \
--dest=org.gnome.ScreenSaver / org.freedesktop.DBus.Introspectable.Introspect
method return sender=:1.7256 -> dest=:1.7286 reply_serial=2
 string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
 <interface name="org.freedesktop.DBus.Introspectable">
 <method name="Introspect">
 <arg name="data" direction="out" type="s"/>
 </method>
 </interface>
 <interface name="org.gnome.ScreenSaver">
 <method name="Lock">
 </method>
 <method name="Cycle">
 </method>
 <method name="SimulateUserActivity">
 </method>
 <method name="Inhibit">
 <arg name="application_name" direction="in" type="s"/>
 <arg name="reason" direction="in" type="s"/>
 <arg name="cookie" direction="out" type="u"/>
 </method>
 <method name="UnInhibit">
 <arg name="cookie" direction="in" type="u"/>
 </method>
 <method name="GetInhibitors">
 <arg name="list" direction="out" type="as"/>
 </method>
 <method name="Throttle">
 <arg name="application_name" direction="in" type="s"/>
 <arg name="reason" direction="in" type="s"/>
 <arg name="cookie" direction="out" type="u"/>
 </method>
 <method name="UnThrottle">
 <arg name="cookie" direction="in" type="u"/>
 </method>
 <method name="GetActive">
 <arg name="value" direction="out" type="b"/>
 </method>
 <method name="GetActiveTime">
 <arg name="seconds" direction="out" type="u"/>
 </method>
 <method name="SetActive">
 <arg name="value" direction="in" type="b"/>
 </method>
 <method name="ShowMessage">
 <arg name="summary" direction="in" type="s"/>
 <arg name="body" direction="in" type="s"/>
 <arg name="icon" direction="in" type="s"/>
 </method>
 <signal name="ActiveChanged">
 <arg name="new_value" type="b"/>
 </signal>
 </interface>
</node>
"
$ dbus-send --session --print-reply --reply-timeout=2000 \
--type=method_call --dest=org.gnome.Tomboy \
/org/gnome/Tomboy/RemoteControl org.freedesktop.DBus.Introspectable.Introspect

 string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!-- NDesk.DBus 0.6.0 -->
<node>
 <interface name="org.freedesktop.DBus.Introspectable">
 <method name="Introspect">
 <arg name="data" direction="out" type="s" />
 </method>
 </interface>
 <interface name="org.gnome.Tomboy.RemoteControl">
 <method name="Version">
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="DisplayNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="HideNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="DisplayNoteWithSearch">
 <arg name="uri" direction="in" type="s" />
 <arg name="search" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="FindNote">
 <arg name="linked_title" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="FindStartHereNote">
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="CreateNote">
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="CreateNamedNote">
 <arg name="linked_title" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="CreateNamedNoteWithUri">
 <arg name="linked_title" direction="in" type="s" />
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="DeleteNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="DisplaySearch" />
 <method name="DisplaySearchWithText">
 <arg name="search_text" direction="in" type="s" />
 </method>
 <method name="NoteExists">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="ListAllNotes">
 <arg name="ret" direction="out" type="as" />
 </method>
 <method name="GetNoteContents">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="GetNoteTitle">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="GetNoteCreateDate">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="x" />
 </method>
 <method name="GetNoteChangeDate">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="x" />
 </method>
 <method name="GetNoteContentsXml">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="GetNoteCompleteXml">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="SetNoteContents">
 <arg name="uri" direction="in" type="s" />
 <arg name="text_contents" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="SetNoteContentsXml">
 <arg name="uri" direction="in" type="s" />
 <arg name="xml_contents" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="SetNoteCompleteXml">
 <arg name="uri" direction="in" type="s" />
 <arg name="xml_contents" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="GetTagsForNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="as" />
 </method>
 <method name="AddTagToNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="tag_name" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="RemoveTagFromNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="tag_name" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="GetAllNotesWithTag">
 <arg name="tag_name" direction="in" type="s" />
 <arg name="ret" direction="out" type="as" />
 </method>
 <method name="GetNotebookForNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="AddNoteToNotebook">
 <arg name="uri" direction="in" type="s" />
 <arg name="notebook_name" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="GetAllNotesInNotebook">
 <arg name="notebook_name" direction="in" type="s" />
 <arg name="ret" direction="out" type="as" />
 </method>
 <method name="AddNotebook">
 <arg name="notebook_name" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="SearchNotes">
 <arg name="query" direction="in" type="s" />
 <arg name="case_sensitive" direction="in" type="b" />
 <arg name="ret" direction="out" type="as" />
 </method>
 <signal name="NoteDeleted">
 <arg name="uri" direction="out" type="s" />
 <arg name="title" direction="out" type="s" />
 </signal>
 <signal name="NoteAdded">
 <arg name="uri" direction="out" type="s" />
 </signal>
 <signal name="NoteSaved">
 <arg name="uri" direction="out" type="s" />
 </signal>
 </interface>
</node>"

注意其中 object name 因各 Service 定義不同,首次查詢可從 / 開始查,Dbus 會答覆其子路徑。

有了 API 界面之後,就可以直接用 dbus-send 送些指令給這些 Services 啦。如下啟動螢幕保護程式。

dbus-send --session --dest=org.gnome.ScreenSaver \
--type=method_call --print-reply --reply-timeout=20000 \
/ org.gnome.ScreenSaver.SetActive boolean:true

參數的格式可參考 DBus 規格中的 Type Signatures

如果你是在 Desktop 環境想查詢測試 DBus APIs, 比較容易的工具是使用 d-feet,這是 Python/GTK 所寫的工具,只消滑鼠點點就可以查詢各種 API 與送出指令訊息。(以下圖片出自 d-feet)

知道了基本的測試工具後,測試期間通常需要觀測訊息的傳送與反應是否正確,此時可以利用 dbus-monitor。它可以用來監測系統中所有的 Dbus messages,方便查詢軟體是否運作正常。

由於安全性的考量,dbus-monitor 預設只能監錄 Session Bus 中的訊息,意即在每個 Login session 中使用者所開啟的軟體。至於 System Bus,像是 Network Manager 等預設是無法存取的,這是避免惡意軟體竊取隱私,如密碼等資訊。

必須手動開啟權限,設定方法是更改以下設定檔,開啟 eavesdrop policy,並重啟 Dbus daemon. 這樣才能竊聽相關通訊。

cat > /etc/dbus-1/system-local.conf
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>

  <policy context="default">
    <!-- All messages may be received by default -->
    <allow receive_requested_reply="false" receive_type="method_call" eavesdrop="true"/>
    <allow receive_requested_reply="false" receive_type="method_return" eavesdrop="true"/>
    <allow receive_requested_reply="false" receive_type="error" eavesdrop="true"/>
    <allow receive_requested_reply="false" receive_type="signal" eavesdrop="true"/>
    <allow eavesdrop="true"/>
  </policy>
  <policy user="root">
      <allow send_destination="*" eavesdrop="true"/>
      <allow receive_sender="*" eavesdrop="true"/>
  </policy>
</busconfig>

詳盡資訊請參考

閱聞 tsung 分享的Debian / Ubuntu Linux 空間釋放 – 清除沒用的檔案一文,也來分享一下自己清理作業系統環境的方法。

自己是 Debian GNU/Linux 的長年使用者。Debian 使用者有個習慣,由於系統實在太穩定,裝好之後終年難得重灌,久而久之系統就會留下徒然佔用空間的廢棄檔案。這些檔案除了使用者個人資料外,不外乎快取、歷史記錄、設定等等,此外就是曾經安裝、編譯軟體時所裝的開發函式庫。這裡分享幾個常用的清理檔案方法。

Personal data

最後是個人檔案,你有許多目錄,需要先找出最佔用磁碟空間的目錄,你可以透過指令列用 du 來看 disk usage. 常用的參數會像如下

du --max-depth=1 -x | sort -n

這個指令的意思是查詢當下目錄所佔用的大小,並依照小到大排列,-x 的意思是只查詢一個檔案系統,方便你找出單一檔案系統中最大的目錄。你也可以用 -h 讓 du 列出易讀格式

如果你不是 geek, 我推薦使用 baobao,圖形化操作界面,加上磁碟佔用派圖,很容易抓出佔用最多空間的檔案。KDE 使用者可以用 Filelight

Image source: Disk Usage Analyzer by Fabio Marzocca

依照我個人而言,佔用最多空間的往往是電子郵件,信件中常常夾了簡報檔、文件等等。如果已經歸檔結案,我常常會把夾檔刪掉,只留下郵件本文存檔。若你用 Evolution,我推薦自己寫得 evolution-remove-attachments

apt-tools cache

從最簡單的系統安裝設定開始,系統就已經裝了許多你用不著得檔案。第一個常見的就是各國語系的說明文件與翻譯,決大多數使用者從來不會去看其他語言的文件,像是我從來沒讀過法文、甚至日文、韓文的 man pages,也不會使用這些語系的使用界面。而大部分軟體因為國際化的關係,往往裝了數國翻譯,如果是 OpenOffice 或 GNOME, KDE 這些大型軟體計劃,佔用的空間還不少呢。你可以安裝 localepurge 來移除不需要的語系。第一次安裝時,系統會問你要保留哪些語系,回答過一次,未來每次透過 apt/aptitude 安裝套件時,它都會自動清理一次。

下載後的 deb 安裝檔常常也佔用很大空間,特別是 OpenOffice, Xorg, kernel 等等,如果你常常升級系統,不知不覺系統就會存下很多暫存的 deb 安裝檔。你可以用 apt-get 來清除它們。

# apt-get autoclean
# apt-get clean

其中 autoclean 是清掉舊版的 deb,系統會保留一份最新版本安裝檔。我個人都使用 autoclean,以免發生意外的時候,沒有最新版本的 deb 檔可以重新裝。一般使用者可以直接以 clean 清除快取。

apt-tools dependency

使用 Linux 時,或多或少會自己編譯一些軟體,需要編譯軟體時,就會需要相關的函式庫。但常常裝完砍掉後,這些相關的開發函式庫還留在系統中變成軟體孤兒。

你除了應該儘量用 apt-get autoremove 或 aptitude 外,也可以用 deborphan 來找軟體孤兒。最常見 (也很危險) 的用法是

# aptitude remove $(deborphan --nice-mode --guess-all)

這樣deborphan 會推估所有系統中不需要的程式,並全部移除。你也可以用以下指令找出最佔用空間的套件。

$ deborphan -a -n|sort -n

懶惰的話,你也可裝 gtkorphan,以圖形化界面管理。

bleachbit (ccleaner for Linux)

雖然新的 Linux 軟體,已經逐漸使用 .local .cache, .config 等目錄設定方式,但是還是有許多軟體會把快取存在 .config 或自己的目錄中,像是 .gnome2, .firefox 等。結果是使用者很難找到快取檔案,若使用 UbuntuOne, Dropbox 等等雲端備份工具,常常連不重要的快取都一起備份了,費時費錢。

上述或指令或工具,看似十分繁複,而且只能管理系統檔案。從 Windows 跳船過來的使用者一定想,是否有類似 CCleaner 的工具,點一點就可以把垃圾檔案清乾淨?

你可以使用 BleachBit (跨平臺),BleachBit 設計了一套相當有彈性的設定描述語言 – CleanerML,支援了許多常見軟體的清除功能,非常類似 CCleaner,軟體會自動偵測可清楚的軟體列表,只消點選要清除的檔案類型,BleachBit 就會自動刪除並計算所騰出空間。沒有 X 圖形界面時,也可以用 bleachbit_cli 指令列。

References

如果你很 Geek, 可以參考 Ubuntu Wiki 上的 Reducing Disk Footprint,上面分享了許多縮減系統大小的奇技淫巧。

另外 Ubuntu 正有計劃要削減安裝光碟大小,未來也會影響系統安裝後的大小。

前一陣子曾經介紹過「雲端備份」,由於 duplicity 支援相當多種不同的網路儲存協定,像是  ftp, ssh/scp, rsync, Web‐DAV, WebDAVs, HSi (Hierarchical Storage Interface), Amazon S3 backends 等等。因此除了本機之外,你也很適合把它用在伺服器上,一樣可以用 GnuPG Public key安全的加密備份檔案。

為了能夠使用 GnuPG,你必須把公鑰傳輸到伺服器上。千萬別把個人的 PGP Private keys 傳到伺服器上,萬一機器被黑了,你的 Key 也就不安全而失效了。

假設你的伺服器是 remote.server, 你的 key id 是 DC76FEB9

gpg  --export DC76FEB9 | ssh [email protected] gpg --import
這樣就可以把公鑰匯入遠端的伺服器帳號中,但要用 GnuPG 加密,你還需要把信任清單 (ownertrust) 傳過去,讓 GnuPG 了解這把金鑰是受到信賴的。否則你可能會看到以下錯誤訊息
===== Begin GnuPG log =====
gpg: 2983CE0C: There is no assurance this key belongs to the named user
gpg: [stdin]: encryption failed: unusable public key
===== End GnuPG log =====
作法是
gpg  --export-ownertrust |env grep DC76FEB9|ssh [email protected] gpg --import-ownertrust
這樣就可以用 duplicity 時,直接指定 –encrypt-key DC76FEB9 這樣來將備份檔案直接用該金鑰簽署。

There are a few wireless driver supports Master mode (infrastructure mode or AP mode), you can manage these interface with iw tools and provide network services for others, just like a wireless router do.

However, many of cards does not support this feature. But you still can use iwconfig to switch to ad-hoc mode, which most of cards support. With ad-hoc mode, the others can directly communicate with you when both agree on the same network name (SSID) and channel.

So, with properly setup, you can create a local wireless network for nearby nodes, or even share your network with others. What I am interested about it’s to share the network with others.

Actually, the modern linux distribution with Network Manager installed has already supported this kind of feature. It’s very easy to setup in Network Manager.

Basically, you just need to setup a ad-hoc network manually, and enable it when you are connected with ethernet or 3g network.

A quick tutorial –

Edit a network, left click the network-manager icon, and select Edit Connections, select Wireless and click on “Add” network.

In the connection editing window, change Mode to Ad-Hoc, and set the SSID you prefer to use.

Switch to IPv4 Settings tab of tab, and change method to “Shared to other computers”. Save the configs.

After you connect to the wan (like pppoe or 3g network), you need to create the ad-hoc network manually.
Left click the network-manager icon, and click on “Create New Wireless Network”.

Just select the connection profile we setup in the previous step, and click Create. That’s it. The network manager will setup your wireless interface and dnsmasq for you.

If you are not using Network Manager, here is my little script to setup an Ad-Hoc network. Use it at your own risk. This is a tips.

偶爾你會需要刪除特定目錄下的空目錄,一個一個去找顯然不太聰明而且相當費時。

可以簡單的利用  find 來找,兩個參數可用,分別是 -depth 與 -empty。另外你可以加上 -type d 讓它只找目錄,不加的話,它會會連空檔案都找出來。

$ find /tmp -depth -empty -type d

配合 -exec 就可以將這些檔案全部刪掉啦。

$ find /tmp -depth -empty -type d -exec rmdir -v {} \;

這是一篇 Tips