Python: call piped commands using subprocess

For example, I want to call external command:
cat /tmp/fruits.txt | grep apple
, depending on if the input is trusted or not, we have the following two options:
  • For untrusted input:
    import subprocess
    cat = subprocess.popen(['/bin/cat', '/tmp/fruits.txt'], stdout=PIPE)
    grep = subprocess.popen(['/bin/grep', 'apple'], stdin=cat.stdout, stdout=PIPE)
    output = grep.communicate()[0]
    print output
  • For trusted input, you can simply set shell=True:
    import subprocess
    output=subprocess.check_output('cat /tmp/fruits.txt | grep apple', shell=True)
    print output


  1. 退出PPS
  2. 如果是Windows 7/Vista,进入文件夹 C:\Users\用户名\AppData\Roaming\PPStream;如果是Windows XP,进入C:\Windows
  3. 编辑并保存文件ppsarea.ini:
  4. 编辑并保存文件psnetwork.ini:
  5. 将上述两个文件设为只读(Read-Only).
  6. 启动PPS

See also

Embed fonts to PDF

  • Use preview (Mac)
    1. Open the PDF in the
    2. Select File -> Print...
    3. Click the PDF button, and then select Save as PDF... from the pop up menu
    4. Choose a filename and save the file. The new PDF file contains the fonts required.
  • Use Adobe Reader X (or XI), See below:

Mac OS X Lion: save as PDF-X

  1. Open /Applications/Utilities/, Select Filters, click the triangle to the right of the "Create Generic PDFX-3 Document" filter
  2. Select "Duplicate Filter"
  3. Open the new "Create Generic PDFX-3 Document Copy" filter, then "Domains", tick "PDF Workflows"
  4. Now when printing, you can click "PDF" button

    then select "Create Generic PDFX-3 Document Copy.qfilter" to create (or save as) PDFX-3 document.

Kindle 3 中文乱码的解决办法

I. 设置中文Locale

  1. 键回到初始页面,按回车键后,在输入框内依次输入以下三条命令:
    ~changeLocale zh-CN
  2. 重启Kindle,具体步骤是, -> -> Settings -> -> Restart 或者按住滑动开关钮15秒就会重启。

II. 中文txt文档乱码问题的解决

  1. 将txt文件转成Unicode或者UTF-8编码。这个办法对于比较短的txt文件有效。
  2. 对于长篇txt文件,即使转成unicode或者UTF-8,几页之后也会变成乱码。所以对txt文件最佳的办法就是用calibre转成MOBI格式。

III. 中文PDF文档空白或乱码问题的解决

原因是所需字体缺失,解决办法是嵌入所需字体重新生成PDF。具体办法是,使用Adobe XI (11.0)或者Adobe X(10.0)打开PDF文档,
  • 打开PDF文档后,选择打印到Adobe PDF (不要选打印机)
  • 打印选项设置(进打印后选择属性),然后在纸张/质量(Paper/Quality)里选择高级选项(Advanced),再选择下载软字体(Download as softfonts)
  • 开始打印后,生成的新PDF就是内嵌字体的了


Java RegEX: parse and extract dollar sign variables from string


extract variables in the form of ${var} in string. e.g. "a ${b} ${c} ${b}", where b and c are variable names.


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class QueryPattern {

 private String _s;
 private List<String> _vars;

 public QueryPattern(String s) {
  _s = s;
  _vars = parseVariables(s);

 public List<String> variables() {
  return _vars;

 public String toString() {
  return _s;

 public String evaluate(Map<String, String> varMap) throws Throwable {
  return evaluate(this, varMap);

 public String evaluate(String[] vars) throws Throwable {
  return evaluate(this, vars);

 public static void main(String[] args) throws Throwable {
  QueryPattern p = new QueryPattern("a \\\\\\${b} ${c}");
  System.out.println(p.evaluate(new String[] { "b", "1", "c", "2" }));

 public static List<String> parseVariables(String s) {
  List<String> vars = new ArrayList<String>();
  Pattern p = Pattern.compile("\\$\\{[a-zA-Z]+\\w*\\}");
  Matcher m = p.matcher(s);
  while (m.find()) {
   int n = 0;
   for (int i = m.start()-1; i >= 0 && s.charAt(i) == '\\'; i--) {
   if (n % 2 != 0) {
   String var = s.substring(m.start() + 2, m.end() - 1);
   if (!vars.contains(var)) {
  if (!vars.isEmpty()) {
   return vars;
  return null;

 public static String evaluate(QueryPattern pattern, Map<String, String> varMap) throws Throwable {
  List<String> vars = pattern.variables();
  String s = pattern.toString();
  if (vars == null) {
   return s;
  for (String var : vars) {
   String value = varMap.get(var);
   if (value == null) {
    throw new Exception("Could not find value for variable: " + var);
   s = s.replaceAll("\\$\\{" + var + "\\}", value);
  return s;

 public static String evaluate(String pattern, Map<String, String> varMap) throws Throwable {
  return evaluate(new QueryPattern(pattern), varMap);

 public static String evaluate(QueryPattern pattern, String[] vars) throws Throwable {
  if (vars.length < 2 || vars.length % 2 != 0) {
   throw new Exception("Invalid length of array. Should be in the form of {\"name\", \"value\"}.");
  Map<String, String> varMap = new HashMap<String, String>(vars.length / 2);
  for (int i = 0; i < vars.length; i += 2) {
   varMap.put(vars[i], vars[i + 1]);
  return evaluate(pattern, varMap);

 public static String evaluate(String pattern, String[] vars) throws Throwable {
  return evaluate(new QueryPattern(pattern), vars);

FreeNX server authenticate failure: nxserver: (nx) Failed login for user=xxx

When setting up freenx server with --setup-nomachine-key option (it uses the default nomachine key pair come with the distribution.) The nx clients failed login with authentication error. And the /var/log/auth.log of the nx server host shows
nxserver[10411]: (nx) Failed login for user=wilson from IP=
The reason is the nomachine key pair came with freenx distribution is no longer valid.


The solution is: generate custom keypair and distribute the key to the nx clients:
  1. On the nx server host, remove the old ssh key pairs for the nx user:
    sudo rm /usr/NX/home/nx/.ssh
  2. On the nx server host, generate new custom key pair:
    sudo /usr/NX/bin/nxsetup --install
    When asking:
    Do you want to use your own custom KeyPair? [y/N]
    Answer is y. It will generate files (key pair) in /usr/NX/home/nx/.ssh/. And /usr/NX/home/nx/.ssh/client.id_dsa.key is the file you need to distribute to your nx clients.
  3. In the configuration of NX client (Nomachine nx client or OpenNX client), import the newly generate key file: /usr/NX/home/nx/.ssh/client.id_dsa.key
  4. Now you should be able to login via nx client...

Mac OS X: how to change file association

  • Right click on the file you want to change the association for and select "Get Info"
  • Change "Opens With" to the application you want.
  • Click the "Change All..." button to change this file association for all files of the same type.

    And click "Continue" button when the confirmation message is prompted:

Mac OS X: check file association information

The user's file association settings is stored in ~/Library/Preferences/ However, it is not a text file. You need to run the following commands to see the information:
defaults read | grep -v LSBundleLocator
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Versions/Current/Support/lsregister -dump

See also:

Mac OS X: Remove duplicated "Open with" menu items by rebuilding LaunchServices database

The "Open with" menu may contain duplicated items when you upgrade the application to a new version. For example, I upgraded my from 10 to 11, then 12. The Open With menu then contains three duplicated items. To clean them up, you can rebuild the LaunchServices database:

  • On Mac OS X 10.5 or later (Leopard, Snow Leopard, Lion or Mountain Lion), run the following command:
    /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user
  • On Mac OS X 10.3 or 10.4 (Panther or Tiger), run the following command:
  • /System/Library/Frameworks/ApplicationServices.framework/\Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user

Mac OS X: find duplicated files using DupeGuru

  1. Download and install DupeGuru.
  2. Add the folders you want to scan for duplicates.
  3. You can mark the duplicates found and send them to Trash.

GWT Developer's Plugin for Firefox 16

  1. Click the link below:
  2. Open it with Firefox

See also

Mac OS X: Bypass the confirmation message when turning on private browsing in Safari

When turning on "Private Browsing" in Safari, it always pops up a confirmation window:

It is annoying. To avoid the confirmation message, you have two options:
  • Option 1: Hold Option key, when click "Private Browsing..." menu item
  • Option 2: Add keyboard shortcut:
    1. "System Preferences..." -> "Keyboard"
    2. Activate "Keyboard Shortcuts" tab, select "Application Shortcuts", then click + button
    3. Application:, Menu Title: Private Browsing, Keyboard Shortcut: Ctrl+Option+P, then click Add button. You can now using the key combo (shortcut) to turn on "Private browsing" mode without seeing the confirmation message.

Mac OS X: add keychain item manually

  1. Open "Keychain Access" in "/Applications/Utilities/Keychain"
  2. File -> "New Password Item..."

Mac OS X: back up your keychain files

Your keychain files are located at ~/Library/Keychains/. You can back them up by making copies of them. e.g.

tar czvf keychains.tar.gz ~/Library/Keychains/*; cp keychains.tar.gz /Volumes/USB/

Eclipse: Indent using spaces instead of tabs

  • The default text editor: Preferences->General->Editors->Text Editors->Insert spaces for tabs
  • The Java editor: Preferences->Java->Code Style->Formatter->Edit->Indentation = "Spaces Only"

Mac OS: Show WIFI password

  1. Open "Keychain Access", go to Applications -> Utilities -> Keychain Access
  2. Keychains: System, Category: Passwords, Select the wireless network, double click to open it.
  3. In the pop-up window, tick "Show password", you will be asked for your login & password, enter them correctly, you can then see the wifi password.

Convert Youtube video to mp3


Linux: schedule a delayed shutdown

  • Shutdown at 20:00:
    nohup shutdown -h -P 20:00 &
  • Shutdown in 60minutes:
    nohup shutdown -h -P +60 &

Android: force apps to install to SD card without root

The android apps can be installed/moved to sd card if the application supports it. However, not all the applications support this. And the default install location for the apps is internal storage which is most likely insufficient. The following approach can change the default install location for the apps to sd card (external storage). which means the all the apps will be installed to sd card. (and it does not require rooting the phone):
  1. Install android sdk and connect your phone to your computer.
  2. Run the following adb commands:
    cd /path/to/android-sdk-macosx/platform-tools
    ./adb devices
    ./adb shell pm getInstallLocation
    ./adb shell pm setInstallLocation 2
  3. To check the install location:
    ./adb shell pm getInstallLocation
    it should return


In Android, Install Location has 3 values:
  • 0[auto] – Let the system decide the best location
  • 1[internal] – Install the application on internal device storage. This means any internal storage provided with your device
  • 2[external] – Install the application on external media. This means any SD, microSD cards attached to your device.
The default value is 0[auto]. You can revert back to the default using the following adb command:
./adb shell pm setInstallLocation 0
On Windows, you might need to install the USB driver to connect your phone to your computer to run the adb commands.

See also

Citrix XenServer: failed to start Ubuntu VM after kernel upgrade

Recently I upgraded my Ubuntu VM to 12.04, which includes the new kernel. However the VM failed to reboot with following error:
Using  to parse /boot/grub/grub.cfg

To fix it,
  1. boot your vm using the following command:
     xe-edit-bootloader -n your_vm_name -p 1
  2. edit /grub/grub.cfg, comment out or remove the whole submenu section.
To avoid this, always remove the old kernels before rebooting. It automatically removes the submenu form grub.cfg. e.g.
aptitude remove linux-image-2.6.38-8-virtual

See also

TCL: for loop with multiple variables

TCL for loop is in the form of
for { init } { test } { next } { body }
. The examples below shows for loops with more than one variables:
  1. Example 1:
    for { set i 0; set j 10 } { $i < $j } { incr i; incr j -1 } {
       puts "$i $j"
    0 10
    1 9
    2 8
    3 7
    4 6
  2. Example 2:
    for { set i 0; set j 10 } { $i < 3 && $j < 7 } { incr i; incr j -1 } {
       puts "$i $j"
    0 10
    1 9
    2 8

connect to your android phone using adb on Mac OS X

  1. Download and install Android SDK. adb (Android Debugging Bridge) is located at platform-tools/ directory.
  2. Connect to your android phone using adb.
    1. On your android phone, turn on USB debugging: Settings -> Applications -> Development -> USB Debugging
    2. Connect the phone to your Mac using the USB cable.
  3. Now you can run following adb commands to connect to your phone:
    /opt/android-sdk-macosx/platform-tools/adb devices
    It should return something like below:
    $ /opt/android-sdk-macosx/platform-tools/adb devices
    * daemon not running. starting it now on port 5037 *
    * daemon started successfully *
    List of devices attached 
    352810040135572 device
  4. You then using adb commands on your android device, e.g. adb shell to browse the phone's file system.
    /opt/android-sdk-macosx/platform-tools/adb -s 352810040135572 shell
  5. More detail about adb commands.
  6. NOTE: remember to turn off USB debugging on your phone.

See Also

Android: configure CSIPSimple with pennytel

To install and configure CSipSimple with Penneytel:

  • Accounts -> Add account
    • Select Other country providers then Pennytel
    • User Name: 888XXXXXXX (10 digits pennytel number)
    • Password: Your_Pennytel_VoIP_Password
    • Click Save button
  • Settings -> Media -> Codecs, enable only g729 codec and disable all the others.


  • To find your pennytel VoIP password, login to pennytel portal, click "Personal VoIP" in the left sidebar, activate "Settings" tab then "VoIP Settings" sub-tab, then click the + icon near "SIP Settings" in the right column.

See also:

Install apk files into Android emulator using adb (android sdk)

  1. Install the Android SDK
  2. Start the emulator:
    /path/to/android-sdk-macosx/tools/emulator -avd
    and make sure you have tick "Setting -> Applications -> Unknown sources"
  3. Install the apk file:
    /path/to/android-sdk-macosx/platform-tools/adb install /path/to/the-app.apk

Android: configure 3CX softphone with Pennytel

To install and configure 3CX Phone to work with Penneytel:
Profiles -> Add New
  • Account:
    • Name: pennytel
    • Display Name: pennytel
  • Credentials:
    • User: 888XXXXXXX (your 10 digits pennytel number)
    • ID: 888XXXXXXX (your 10 digits pennytel number)
    • Password: Your_Pennytel_VoIP_Password
  • Server Settings:
    • I am Out of Office: (DO NOT tick)
    • Local PBX IP:
    • External PBX IP:
    • PBX port: 5060
    • STUN Server: (empty)
    • 3CX Tunnel: (DO NOT use/change)
    • Proxy:
  • Audio Settings:
    • Audio options: NO CHANGE
    • Audio codecs: NO CHANGE
  • Other Settings:
    • Advanced: NO CHANGE
    • Integration: NO CHANGE


  • To find your pennytel VoIP password, login to pennytel portal, click "Personal VoIP" in the left sidebar, activate "Settings" tab then "VoIP Settings" sub-tab, then click the + icon near "SIP Settings" in the right column.

See also: