Aug 23

Unix/GNU Linux 上的 X11 图形程序会从系统的 /etc/profile 以及用户目录的 $HOME/.bashrc、$HOME/.bash_profile、$HOME/.xprofile 等处读取环境变量。例如 GNU Emacs、Code::Blocks、CodeLite、Eclipse 等均可从系统的环境变量中获取需要的环境变量。尽管 Mac OS X 是类 Unix 系统,但毕竟它的图形界面不是由 X11 提供的,因此,它上面的图形程序获取环境变量的方式也是不同的。由于 Mac OS X 中图形程序有多种运行方式,例如从终端调用命令行运行、在 Finder 、Launchpad 以及 Dock 上点击图标运行或者用 SpotLight 调用,这几种运行方式下图形程序的环境变量读取以及生效方式也不尽一致。

首先,谈谈终端环境以及由终端调用的程序(在 Bash Shell 中)如何读取环境变量。根据 /etc/profile 中的设置可以看到,Mac OS X 系统会借助 /usr/libexec/path_helper 程序设置路径变量 PATH。path_helper 会分别读取 /etc/paths、/etc/paths.d/ 与 /etc/manpaths、/etc/manpaths.d/ 中的设置来获取 PATH 与 MANPATH 的环境变量。之后 /etc/profile 还会综合 /etc/bashrc 给出 Shell 中所有系统级环境变量的设置。因此,系统级的环境变量 PATH 的设置可通过修改 /etc/profile、/etc/bashrc 与 /etc/paths.d/ 等相关文件来实现,除此而外的系统级环境变量则可在 /etc/profile、/etc/bashrc 中设置。有一点值得指出,那就是 MANPATH 变量,通常它是不需要设置的,这是因为手册页的搜索除去用 MANPATH 变量配置之外,还可以在 PATH 的相对路径中搜索。至于 Shell 中用户级环境变量的设置,与 Linux 中一样,首先继承来自 /etc/profile 中的系统级环境变量,再根据 Shell 是不是登录 Shell 决定是否读取用户家目录中的 $HOME/.bashrc 或 $HOME/.bash_profile 中的环境变量。一般为了避免配置重复出现,无论登录还是非登录 Shell,均做如下配置

$ cat > ~/.bash_profile << EOF
if [ -f ~/.bashrc ]; then 
    source ~/.bashrc
fi
EOF

相关环境变量的设置都在 $HOME/.bashrc 中进行。这就给出了 Shell 中所有用户级环境变量的配置方法。对于从终端调用的(无论是否是图形界面的)用户级程序而言,环境变量直接继承自 Shell 中所有用户级环境变量。例如从终端打开 Code::Blocks 程序

$ open -a CodeBlocks.app

随后在 Settings -> Compiler...,Global Compiler settings -> Compiler settings -> Other options 中填入 `echo $PATH`,接着随便写一段简单的 C/C++ 程序并点击 Build,在 Code::Blocks 日志框中便会看到环境变量 PATH 的输出。很容易验证 Code::Blocks 确实是从 Shell 中读取了环境变量。先退出 Code::Blocks,记得退出时选择保存设置,因为还要用它进行同样的测试。请记得在测试完了之后,删掉 Code::Blocks 中全局的编译选项设置。为了做一个比较,可以尝试从 Launchpad 中点击 Code::Blocks 图标启动,做同样的尝试,会发现此时 echo $PATH 没有在日志窗口中输出,这表明从 Launchpad 中启动程序不会继承终端程序的环境变量。

那么除了 Terminal.app 之外,对于那些从 Finder、Launchpad 以及 Dock 处启动或者用 SpotLight 调用的程序,是如何读取环境变量的呢?在 Mountain Lion 之前,从那些位置启动的图形界面程序会从 $HOME/.MacOSX/enviroment.plist 文件继承环境变量;但是自 Mountain Lion 之后,~/.MacOSX/enviroment.plist 失效,只有通过 launchtl setenv 命令设置的环境变量才有可能被它们继承,而且设置完必须重启 Finder、Dock 以及 Spotlight 才能生效,具体取决于程序从哪儿被调用?

先来谈谈 ~/.MacOSX/enviroment.plist 的配置,尽管 Mountain Lion 版本已经过时,但难保不会有一些老的机器会停留在那些版本上。通常,~/.MacOSX/environment.plist 文件并不存在,需要先创建再编辑。例如

$ mkdir ~/.MacOSX && touch  ~/.MacOSX/enviroment.plist

根据 ~/.bashrc 中设置的环境变量情况,利用 defaults 命令操作该文件,例如

$ defaults write $HOME/.MacOSX/environment.plist PATH "$PATH”
$ defaults write $HOME/.MacOSX/environment.plist JAVA_HOME "$JAVA_HOME”
$ defaults write $HOME/.MacOSX/environment.plist ANDROID_HOME "$ANDROID_HOME"

注意上述 defaults 命令是将当前终端中的 PATH、JAVA_HOME 与 ANDROID_HOME 写入了 ~/.MacOSX/environment.plist。至于编辑 ~/.MacOSX/environment.plist,最好用 Xcode.app,例如

$ open -a Xcode.app ~/.MacOSX/enviroment.plist

设置调整完成,可以再试试从 Launchpad 中点击 Code::Blocks 图标启动,做前面一样的测试,会发现此时 echo $PATH 在日志窗口中输出正常。

现在来谈谈 Mountain Lion 版本以后,用 launchctl setenv 设置图形界面程序的环境变量的方法。从当前终端运行

$ launchctl setenv PATH “$PATH"

别急着作测试,因为从 Mac OS Yosemite 开始,光这样设置,从 Finder、SpotLight、Launchpad 以及 Dock 点击图标运行的程序还是不会继承这些变量。对于从 Launchpad 或 Dock 中启动的程序,需重启 Dock 才能让设置生效:

$ killall Dock

对于从 Finder 中启动的程序,需重启 Finder 才能让设置生效:

$ killall Finder

对于从 Spotlight 中启动的程序,需重启才能让设置生效:

$ killall Spotlight
$ killall SystemUIServer

好了,有了这些操作之后,再试试从 Launchpad 中点击 Code::Blocks 图标启动,做前面一样的测试,会发现此时 echo $PATH 在日志窗口中输出正常。

但是可以看到,这样的操作无比麻烦。为了省去这些麻烦,可以建立一个用户级的服务来替代这些操作过程。先创建

$ mkdir -p ~/.local/bin
$ cat > ~/.local/bin/environment.sh <<EOF
#!/bin/sh

set -e

syslog -s -l warn "Set environment variables with ~/.local/bin/environment.sh \$(whoami) - start"

launchctl setenv PATH "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/local/android-sdk-manager/platform-tools:/usr/local/android-sdk-manager/tools:/usr/local/apache-ant/bin:/usr/local/mysql/bin:/usr/local/MacGPG2/bin:/usr/texbin:"
launchctl setenve JAVA_HOME "/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home"
launchctl setenv ANDROID_HOME "/usr/local/android-sdk-manager/"

osascript -e 'tell app "Dock" to quit'
osascript -e 'tell app “Finder" to quit'
osascript -e 'tell app “Spotlight" to quit'
osascript -e 'tell app "SystemUIServer" to quit'

syslog -s -l warn "Set environment variables with ~/.local/bin/environment.sh \$(whoami) - complete"
EOF
$ chmod +x ~/.local/bin/environment.sh

接着再创建服务配置文件

$ nano -w ~/Library/LaunchAgents/org.easior.environment.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>org.easior.environment.plist</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/easior/.local/bin/environment.sh</string>
    </array>
    <key>KeepAlive</key>
    <false/>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

并启动它

$ launchctl load -w ~/Library/LaunchAgents/org.easior.environment.plist

现在来看看以上设置对于环境变量 PATH 带来了怪异现象。首先,第三方终端程序 iTerm.app 作为图形程序,将继承自 launchctl setenv 设定的环境变量 PATH;其次,Mac OS 自带的终端程序 Terminal.app 不会继承来自 launchctl setenv 设置的环境变量,它仍按 Shell 的标准方法设置 PATH 变量;再次,由 XQuartz 提供的 X11.app 中终端程序 xterm 将既会继承由 launchctl setenv 设定环境变量 PATH,还会再次执行登录 Shell,也即会再次继承系统级的 PATH 变量。如此一来,若既在 ~/.bashrc 或 ~/.bash_profile 中设置 PATH,也在 ~/.local/bin/environment.sh 中设置 PATH,且这两个 PATH 设置不一致的话,例如

$ cat >> ~/.bashrc << EOF
~/.local/bin
EOF
$ launchctl setenv PATH "$HOME/bin"
$ killall Dock

那么从 Launchpad 启动的这三个终端的 PATH 变量将会各不相同。为了避免这种情况的发生,建议在 ~/.bashrc 或者 ~/.bash_profile 中设置

if [ ! `launchctl getenv PATH` == "" ]; then
   export PATH=.:`launchctl getenv PATH`
fi

这样一来,每个终端启动的 PATH 均是一致的。还有一点需要指出:launchctl setenv PATH 设置为空与不设置它,这是两码事。例如

$ launchctl getenv PATH ""
$ killall Dock

现在试试从 Launchpad 或 Dock 调用 iTerm.app,会有意想不到的事情发生。

除了 launchctl setenv 的方法之外,修改 Mac OS X 图形程序的 Info.plist 文件中的 LSEnvironment 变量也可以设置需要读取环境变量。例如,在 Finder 的 /Applications 目录鼠标右击 Codeblocks.app 图标 -> Show package contents,接着用 Xcode.app 打开 Contents 目录的 info.plist 文件,在其中增加一个新的 key/dict 对:

<key>LSEnvironment</key>
<dict>
     <key>PATH</key>
<string>/Users/James/.rvm/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:</string>
</dict>

保存完改动并在命令行中执行

$ /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user 
$ killall Finder

再试试从 Launchpad 中点击 Code::Blocks 图标启动,还是做与前面一样的测试,看看 echo $PATH 在日志窗口中输出。为了 Code::Blocks 能正常工作,测试完成后请去掉 Info.list 中的 LSEnvironment 设置。

另外,还有些图形程序,本身提供了设定环境变量的方法。例如对于 GNU Emacs 而言,要继承环境变量可直接在 Emacs 中配置。例如

$ cat >> ~/.emacs <<EOF
(setenv “PATH” (concat (getenv “PATH”) “:” “/opt/local/bin” “:” “/opt/local/sbin”))
EOF

能让 GNU Emacs 的子进程直接读取 PATH 变量。

Aug 23

Homebrew 是一个由 Ruby 语言开发的 Mac OS X 上的第三方包管理工具,它使 Mac OS X 系统更加完整。Homebrew 能够判断 Mac OS X 系统中现有组件的状况,并能够依赖这些已有组件进行安装,而不必重新下载一套重复组件。这一点与 Mac OS X 上其他的第三方包管理工具不同。实际上,Mac OS X 上的第三方包管理工具有很多,例如 MacPortsFinkpkgsrcGentoo Prefix 等等。除 Homebrew 之外,这些第三方包管理工具均会把需要的所有组件全部安装到系统的某个目录(例如 /opt 目录),带来的问题就是 Mac OS X 系统很多已经有的组件都要重新下载安装,这除了带来系统臃肿不够整洁之外,还有可能带来冲突。Homebrew 本身使用 Git 管理,升级非常方便。它的项目主页在 http://brew.sh/

零、准备工作

Homebrew 的工作过程中需要使用编译器、Git 等工具,这些工具均由 Apple 官方的集成开发环境 Xcode.app 工具提供。它的安装方法有两种,一种是进入 Apple 的应用商店下载 Xcode;另一种是去 Apple 开发者主页 https://developer.apple.com/xcode 去下载 Xcode,不过开发者主页下载前一般需要先免费注册一下。下载安装完成后,执行下述命令

$ xcode-select --install

安装 Homebrew 真正需要的命令行工具。实际上,作为安装 Homebrew 的前提,仅需要下载 Xcode.app 的命令行工具,如果注册了 Apple 开发者的话,可直接到 https://developer.apple.com/downloads/ 页面下载它而不必安装完整的 Xcode.app 包。

一、Homebrew 的安装

Homebrew 默认会被安装在 /usr/local/ 目录。但是该目录非普通用户所有,相关操作需要管理员权限,普通用户需要 sudo 权限。若想免去 sudo 的麻烦,可更改目录的属主

$ sudo chown -R `whoami` /usr/local

这对于非服务器版本的 Mac OS X 系统的使用并无大碍。Homebrew 由 Ruby 语言开发,安装当然也只需要用 ruby 命令即可。先确认 Mac 系统上已经默认安装了 ruby:

$ ruby --version

安装 Homebrew 只需要如下的一条命令

$ ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"

以上脚本执行完成后,Homebrew 会被安装在默认位置,可执行下述命令查看

$ brew --prefix
/usr/local

由于 /usr/local 已在系统 PATH 之中,Homebrew 已无须任何配置。

当然,Homebrew 也可被安装其他指定位置。为了更加清晰地了解安装过程,此地以家目录下的 Developer 目录为例:

$ mkdir ~/Developer/ && cd ~/Developer
$ git clone https://github.com/mxcl/homebrew.git

由于 Homebrew 没有装载默认位置,需要对它稍作配置。将 Homebrew 加入系统环境变量 PATH 中:

$ echo "export PATH=\$PATH:\$HOME/Developer/homebrew/bin" >> ~/.bashrc

环境变量的设置一般需退出并重新打开终端才能生效。为了立即生效,可执行下述命令

$ source ~/.bashrc

确认一下此种方式下面 Homebrew 的安装位置

$ brew --prefix

为了确认 Homebrew 运行时,对系统中各个目录时候有权限等问题,可执行下述命令诊断

$ brew doctor

二、Homebrew 的基本用法

在 Mac OS X 中没有提供想要的软件,可以使用 Homebrew 安装;这里以安装 wget 为例,先在 Homebrew 中查找有没有需要的软件(或者说 formula)

$ brew search wget

如果幸运的话,brew 包含了该软件的 formula,那么可执行

$ brew install wget

所有由 Homebrew 安装的包将被装入 `brew --prefix`/Cellar,然后通过软链接到 `brew --prefix` 目录中。例如

$ cd `brew --prefix`
$ find Cellar -iname 'wget'
Cellar/wget/1.15
Cellar/wget/1.15/bin/wget
Cellar/wget/1.15/share/man/man1/wget.1
$ ls -l bin/wget
bin/wget -> ../Cellar/wget/1.15/bin/wget

若想删掉由 homebrew 安装包,非常简单

$ brew uninstall wget

若不幸没有找到需要的 formula,可到邮件列表 homebrew@librelist.com 中反映,或者自己动手写一个 formula。创建 Homebrew formula 的典型方法如下:先用 Homebrew 下载源码包:

$ brew create http://foo.com/bar-1.0.tgz

该命令会创建原始的 formula,详见 `brew --prefix`/Library/Formula/bar.rb。接着编辑该 formula 让它工作,编辑的样例可在 Homebrew 系统中查找,例如

$ brew edit wget
Homebrew formulae are simple Ruby scripts:
require "formula"

class Wget < Formula
  homepage "http://www.gnu.org/software/wget/"
  url "http://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz"
  sha1 "f3c925f19dfe5ed386daae4f339175c108c50574"

  def install
    system "./configure", "--prefix=#{prefix}"
    system "make", "install"
  end
end

不管怎么样,Homebrew 的开发是在 Ruby 与 git 下进行的,因此它的修改以及与上游更新合并均非常容易。

更新本地已安装的软件包

$ brew update
$ brew upgrade --all

清理残留的旧版本及相关日志

$ brew cleanup

三、Homebrew 的扩展源

当然,若 Homebrew 官方提供的包不能满足需要的话,那么还可以为 Homebrew 安装扩展源,甚至可以安装某个包的多个版本。例如,Mac OS X 已经自带了 PHP,若想安装其他版本的 PHP,可利用 josegonzalez 提供的 PHP 扩展,实际上若网络正常工作的话,下述命令会告知有哪些扩展源提供了 PHP:

$ brew search php

先增加扩展源

$ brew tap josegonzalez/php

现在可以安装需要的包了

$ brew install php55

删掉扩展源提供的安装包还是非常简单:

$ brew uninstall php55

删除 tap 仓库

$ brew untap josegonzalez/php

由于 Mac OS X 中的服务是由 launchctl 管理,对于习惯 Linux 的用户,不一定习惯这种服务管理方式。这就不得不提一下扩展源 gapple/services 提供的 Homebrew-services 了,它提供了类似管理 Linux 服务的命令。先安装扩展源

$ brew tap gapple/services

管理由 Homebrew 安装的服务,例如

$ brew install tomcat
$ brew services start catalina

打开浏览器查看 Tomcat 是否正常运行,注意到 Tomcat 的默认端口是 8080,因此

$ open http://127.0.0.1:8080 &

停止服务的方法也很简单

$ brew services stop catalina

若利用 Homebrew 安装了很多服务,想查看一下,也很简单,例如

$ brew install mysql nginx
$ brew services list

列出已安装的 tap 仓库

$ brew ls-taps

四、更多 Homebrew 指令

显示与 Homebrew 相关的系统信息

$ brew config

显示软件内容信息

$ brew info wxmac

根据列出的信息使用额外的编译选项安装 wxmac 包,例如

$ brew install wxmac --with-stl

对于已安装的包,也可重新选择编译选项安装

$ brew reinstall wxmac --with-static

Homebrew 可一次安装多个包

$ brew install w3m gnutls cscope

显示包依赖

$ brew deps w3m

用浏览器打开 Homebrew 的主页

$ brew home

用浏览器打开 w3m 的 formula 页面

$ brew home w3m

列出已安装的软件

$ brew list

查看已安装的无依赖包

$ brew leaves

查看 Homebrew 帮助

$ brew -h

若需要更多的帮助命令,可执行

$ brew commands

也可以查看 Homebrew 的手册页获得帮助

$ man brew

五、删除 Homebrew

万一用的不爽了,卸载 Homebrew 的方法也很简单

$ cd `brew –prefix`
$ rm -rf Cellar
$ brew prune
$ rm -rf Library .git .gitignore bin/brew *.md share/man/man1/brew.1
$ rm -rf ~/Library/Caches/Homebrew ~/Library/Logs/Homebrew /Library/Caches/Homebrew

此种卸载方式对于系统来说非常干净。

六、附录

Homebrew 也被移植到了 Linux 上,称为 Linuxbrew。虽然各种 Linux 发行都带有自己的包管理工具,诸如 apt-get、yum、pacman、emerge 等等,但对那些工作于服务器版本但没有管理员权限的 Linux 用户来说,Linuxbrew 仍有用武之地,可通过它无须管理员权限安装一些管理员没有提供的或者比系统中更新的包。它的项目主页:http://brew.sh/linuxbrew/

在安装 Linuxbrew 之前,需要先准备好依赖。例如在 Fedora 上,先执行如下命令

$ sudo yum groupinstall 'Development Tools'
$ sudo yum install curl git ruby bzip2-devel curl-devel expat-devel ncurses-devel zlib-devel

接着,将 Linuxbrew 从 GitHub 克隆下来:

$ mkdir ~/Developer/
$ git clone https://github.com/Homebrew/linuxbrew.git ~/Developer/linuxbrew

简单配置

$ echo "export PATH=\$HOME/Developer/linuxbrew/bin:\$PATH
      export C_INCLUDE_PATH=\$HOME/Developer/linuxbrew/include
      export LIBRARY_PATH=\$HOME/Developer/linuxbrew/lib" >> ~/.bashrc

然后执行:

$ source ~/.bashrc

这样子 Linuxbrew 就算装好了。

Jun 19

Mac OS X 是由美国苹果公司开发的操作系统,通常它运行在如 MacBook、Mac 等个人电脑中。事实上,经过适当的配置以及软件的安装,也可以以 Mac OS X 为基础构建服务器。这里就来介绍一下如何在 Mac OS X 运行 Web 服务器。由于 Mac OS X 内置了 Apache 和 PHP,因此,几乎非常少的配置即可让 Web 服务运行在 Mac OS X 上。不过,这种非常少的配置是需要用户具有比较良好的 Unix 使用经验做基础的,后面的介绍也基本围绕着这种方式展开的。由于 Mac OS X 是一款非常优秀的操作系统,想要把 Web 服务的配置变得平易近人,也是非常容易的。OS X Server 就为用户提供了诸如 Web 服务、VPN 服务、FTP 服务等简明的图形化操作,有需要的用户可去 App Store 下载、安装 Server.app。除此而外,单就 Web 服务而言,另有 XAMPP、MAMP Pro 等已经打包好的开箱即用软件可供使用。

一、启动 Apache

在 Mac OS X 10.8 以前启动 Apache 很简单,只需在系统设置偏好(System Preferences)中设置 Web 共享(Web Sharing)即可。不过自 Mac OS X 10.8 以后,Web 共享(Web Sharing)取消了。因此,启动 Apache 需采用下述方法,先打开终端(Terminal.app),然后在终端运行

$ sudo apachectl start

再输入帐号密码,这样 Apache 就运行了。为了确认 Apache 是否正常工作,可在浏览器中输入 http://127.0.0.1 ,或者在终端输入

$ open http://127.0.0.1 &

正常情况下,就可以看到一个内容为 “It works!” 的页面,该页面对应 /Library/WebServer/Documents/index.html.en 文件。其中,/Library/WebServer/Documents/ 是 Apache 的默认(系统级)根目录。若想获知 Apache 的版本,可运行

$ apachectl -v
Server version: Apache/2.2.26 (Unix)
Server built:   Jun 20 2014 13:57:09

便会看到 Mac OS X 自带 Apache 版本信息。 为了更好的配置 Apache 服务,这里再来指出几个非常重要的文件与目录。第一个是 Apache 服务的配置文件目录,位于 /etc/apache2,里面包含了 Apache 服务的基本配置文件 httpd.conf。/etc/apache2 中还有很多其他文件和目录,在后面会陆续涉及到其中的一些。第二个是管理 Apache 服务的启动、停止等配置的文件,位于 /Library/LaunchDaemon/org.apache.plist。第三个是 Apache 的日志文件目录,位于 /var/log/apache2/,如果 Apache 启动后有任何问题,记得去这个地方看看,兴许就能找到解决问题的蛛丝马迹。

二、开启 PHP 支持

在终端中运行

$ sudo nano -w /etc/apache2/httpd.conf

打开 Apache 的配置文件,找到如下的行

#LoadModule php5_module libexec/apache2/libphp5.so

把前面的#号去掉,也即

LoadModule php5_module libexec/apache2/libphp5.so

保存 Apache 的配置文件。该来配置 PHP 了,首先查看 PHP 的配置文件 /etc/php.ini 是否存在,若没有的话,请运行

$ sudo cp /etc/php.ini.default /etc/php.ini

适当的调整一下配置,通过编辑 /etc/php.ini 文件,也即

$ sudo nano -w /etc/php.ini

来配置各种 PHP 功能。比如:

;调整时区
date.timezone = "Asia/Shanghai"
;通过 display_errors 来控制是否显示 PHP 程序的报错信息,这在调试 PHP 程序时非常有用
display_errors = Off

再来看一下 PHP 与 Apache 的整合配置文件:

$ sudo nano -w /etc/apache2/other/php5.conf
<IfModule php5_module>
    AddType application/x-httpd-php .php 
    AddType application/x-httpd-php-source .phps

    <IfModule dir_module>
        DirectoryIndex index.html index.php
    </IfModule>
</IfModule>

为了让所有的配置生效,需运行

$ sudo apachectl restart

重启 Apache,这样 PHP 就可以用了。

为了测试 Apache 服务器上的 PHP 是否正常工作,可在终端中运行

$ mkdir -p ~/Sites

来创建 Apache 的用户级根目录,随后再在用户级根目录中新建一个 info.php 文件

$ cat > info.php << EOF
<?php
    phpinfo();
?>
EOF

不妨假设 Mac OS X 系统用户 james 便是 Apache 服务的主要使用者,以上 Apache 的用户级根目录都是在 james 用户的家目录创建的。于是,在 Mac OS X 的浏览器 Safari 的地址栏中输入 http://127.0.0.1/~james/info.php,或者

$ open http://127.0.0.1/~james/info.php &

便会看到有关 PHP 的信息,比如 Mac OS X 10.9 中内置 PHP 版本号是 5.3.13。

三、安装 MySQL

由于 Mac OS X 没有内置 MySQL,所以需要手动安装,可从 MySQL 的官方网站 http://mysql.com/downloads/mysql/MySQL 下载。目前 MySQL 的最稳定版本是 5.6,选择合适版本,如这里选择了 mysql-5.6.16-osx10.7-x86_64.dmg。进入下载页面,会提示注册 Oracle 帐号或者以 Oracle 帐号登录;当然,也可选择 “No thanks, just start my download.” 直接下载,例如

$ curl -O http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.16-osx10.7-x86_64.dmg

打开下载的 dmg 文件,会发现里面有 4 个文件,分别是 mysql-5.6.16-osx10.7-x86_64.pkg、MySQLStartupItem.pkg、MySQL.prefPane 与 ReadMe.txt。首先点击安装 mysql-5.6.16-osx10.7-x86_64.pkg,这是 MySQL 主安装包。一般情况下,安装文件会自动把 MySQL 主程序安装到 /usr/local 下。为了让 MySQL 在 Mac OS X 开机时自动启动,安装包里提供了 MySQLStartupItem.pkg,安装它。有了它,可以在终端控制 MySQL 的运行、重启以及关闭之类,例如

$ sudo /Library/StartupItems/MySQLCOM/MySQLCOM start
$ sudo /Library/StartupItems/MySQLCOM/MySQLCOM restart
$ sudo /Library/StartupItems/MySQLCOM/MySQLCOM stop

若想以图形界面方式管理 MySQL 的启动,可安装包里的 MySQL.prefPane。安装它之后,就可在“系统设置偏好”中看到 MySQL 的图标,通过它就可以控制 MySQL 是否开启以及开机时是否自动运行。另外,使用 PHP 连接 MySQL 可能会报错

Can’t connect to local MySQL server through socket ‘/var/mysql/mysql.sock‘

或使用 localhost 无法连接 MySQL 而需要 127.0.0.1,原因是连接时 PHP 默认去找 /var/mysql/mysql.sock,但 MAC 版的 MySQL 改动了文件位置,放在 /tmp 下了。处理办法是按如下修改 php.ini:

$ nano -w /etc/php.ini
mysql.default_socket = /tmp/mysql.sock

到这里 MySQL 就基本安装完毕了。 通过运行

$ sudo echo /usr/local/mysql/bin >> /etc/paths.d/80-mysql

将 mysql 的路径加入系统环境变量 PATH 中;当然,也可以代之以用户级环境变量设置,例如

$ echo "export PATH=/usr/local/mysql/bin:\$PATH" >> ~/.bashrc'

这样就可以在终端中比较简单地通过命令进行相应的操作。 在 MySQL 没有启动时,直接运行 mysql 或 mysqladmin 命令会提示

Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’ (2)

这就需要我们先通过控制面板或者直接运行

$ sudo /usr/local/mysql/support-files/mysql.server start
$ sudo /usr/local/mysql/support-files/mysql.server restart

命令来启动 MySQL,之后再运行 mysql 或 mysqladmin 命令就正常了。比如安装完毕后,MySQL 的 root 默认密码为空,如果要设置密码可以在终端运行

$ mysqladmin -u root password "mysqlpassword"

来设置,其中 mysqlpassword 即 root 的密码。再如查看 MySQL 的版本

$ mysql -V

注意:Mac OS X 的升级或其他原因可能会导致 MySQL 启动或开机自动运行时,在 MySQL 操作面板上会提示 “Warning:The /usr/local/mysql/data directory is not owned by the ‘mysql’ or ‘_mysql’”,这应该是某种情况下导致 /usr/local/mysql/data 的宿主发生了改变,只需要运行

$ sudo chown -R _mysql /usr/local/mysql/data

即可。 MySQL 的默认日志位于它的数据目录,也即 /usr/local/mysql/data 之中。不过默认的错误日志文件名是主机名生成的,稍作配置

$ sudo nano -w /usr/local/mysql/my.cnf
[mysqld]
log-error=/usr/local/mysql/data/mysqld.log

由于它与系统目录分离,因此 mysql 不会自动清除日志,可以使用它自带的 mysql-log-rotate 脚本,例如

$ sudo /usr/local/mysql/support-files/mysql-log-rotate

或手动编写脚本清除旧日志。

四、MAMP 的简单应用

1、WordPress 的配置

先通过下述命令行为 WordPress 创建一个名为 db_wordpress 的数据库,并设置数据库用户 wordpress_user、密码为 654321 以及对 WordPress 数据库赋予所有权限:

$ sudo mysql -uroot -p
mysql> create database db_wordpress;
mysql> grant all privileges on db_wordpress.* to 'wordpress_user'@'127.0.0.1' identified by '123456';
mysql> FLUSH PRIVILEGES;
mysql> EXIT

数据库创建完成之后,开始安装

$ curl -O http://wordpress.org/latest.zip
$ sudo unzip latest.zip -d /Library/WebServer/Documents/
$ sudo mv /Library/WebServer/Documents/wordpress/wp-config-sample.php /Library/WebServer/Documents/wordpress/wp-config.php

接着根据前面创建的数据库信息配置 WordPress:

$ sudo nano -w /Library/WebServer/Documents/wordpress/wp-config.php

// ** MySQL settings – You can get this info from your web host ** //
/** The name of the database for WordPress */
define(‘DB_NAME’, ‘db_wordpress‘);

/** MySQL database username */
define(‘DB_USER’, ‘wordpress_user‘);

/** MySQL database password */
define(‘DB_PASSWORD’, ‘123456‘);

/** MySQL hostname */
define(‘DB_HOST’, ‘127.0.0.1‘);

为了让所有的 WordPress 设置生效,需重启 Apache

$ sudo apachectl restart

在浏览器输入 http://127.0.0.1/wordpress 进入 WordPress;或者

$ open http://127.0.0.1/wordpress &

第一次进入 WordPress 时,需要完成它的初始化安装。欢迎来到 WordPress 的世界,当然,还有后续的管理工作要做,例如

$ sudo nano -w /Library/WebServer/Documents/wordpress/.htaccess
Options +FollowSymLinks

有关这些的介绍,请查阅官网的相关介绍。

2、MediaWiki 的配置

先为 MediaWiki 创建一个数据库,也即

$ sudo mysql -uroot -p
mysql> create database db_mediawiki;
mysql> grant all privileges on db_mediawiki.* to 'mediawiki_user'@'127.0.0.1' identified by '654321';
mysql> FLUSH PRIVILEGES;
mysql> EXIT

创建了名为 db_mediawiki 的数据库,设置用户 mediawiki_user,密码为 654321,对 MediaWiki 数据库赋予所有权限。数据库创建完成之后,开始安装 MediaWiki:

$ curl -O http://releases.wikimedia.org/mediawiki/1.22/mediawiki-1.22.3.tar.gz
$ tar zxvf mediawiki-1.22.3.tar.gz -C ~/Sites/

重启 Apache

$ sudo apachectl restart

让所有的 MediaWiki 设置生效。由于 MediaWiki 是安装在 Apache 的用户级根目录中,需在浏览器中输入 http://127.0.0.1/~james/mediawiki,或者

$ open http://127.0.0.1/~james/mediawiki 

第一次打开 MediaWiki 会需要输入相关信息,并点击 Install/Upgrade Database 完成最后的安装。安装完成之后,会生成 Localsetting.php。将它下载到本地,再将它复制到 ~/Sites/mediawiki 目录,也即

$ cp /path/to/Localsetting.php ~/Sites/mediawiki

设置访问权限如下

$ sudo nano -w /etc/apache2/users/mediawiki.conf
 Alias /mediawiki "/Users/james/Sites/mediawiki"

 <directory "/Users/james/Sites/mediawiki/">
       Options Indexes MultiViews FollowSymLinks
       AllowOverride None
       Order allow,deny
       Allow from all

 <directory "/Users/james/Sites/mediawiki/upload/">
    AllowOverride None
    AddType text/plain .html .htm .shtml
 # php_admin_flag engine off  # This doesn't seem to work.

  RewriteEngine on
  RewriteRule ^/wiki/en/(.*)$ /mediawiki/wiki.phtml?title=$1

至此,MediaWiki 站点基本完工了。

3. phpBB3 的配置

先为 phpBB3 创建数据库
$ mysql -u root -p
mysql> create database db_phpdb3;
mysql> grant all privileges on db_phpbb3.* to 'phpbb3_user'@'127.0.0.1' identified by '654123';
mysql> FLUSH PRIVILEGES;
mysql> EXIT
现在开始搭建 phpBB 论坛,目前 phpBB 的稳定版本是 3.0.12:
$ curl -O -J -L http://prdownloads.sourceforge.net/phpbb/phpbb-3.0.12.tar.bz2
将解压的 phpBB3 目录放到 ~/Sites 下:
$ tar jxvf phpbb-3.0.12.tar.bz2 -C ~/Sites
$ chmod 644 ~/Sites/phpbb/config.php
$ open http://127.0.0.1/~james/phpbb &
填写所连接数据库以及用户信息等。填写完成后开始安装。完成最后的安装之前,别忘了先将 phpBB 下的 install 目录删除
$ rm -rf ~/Sites/phpbb/install
 
本地化 phpBB,先到官方网站下载并解压语言包,例如下载简体中文包
$ curl -O -J -L https://www.phpbb.com/customise/db/download/id_91456
$ tar jxvf mandarin_chinese_simpliefied_script_1.0.3.tar.bz2
$ cd mandarin_chinese_simpliefied_script_1.0.3/mandarin_chinese(simpliefied_script)_1.0.3
$ cp -r * ~/Sites/phpbb/
后续操作,请参考 https://www.phpbb.com/kb/article/how-to-install-a-language-pack。

Mar 19

一、网络设置相关

1、网卡的物理地址的动态重置

出于某些需求,例如网络中的 IP 地址或网络帐号与网卡物理地址绑定,使得多个设备无法切换上网,可尝试临时更改物理地址。不过,系统偏好设置是不能修改网卡物理地址的,这就是命令行的用武之地了。具体来说,若心中已有想修改的物理地址,例如 00:1f:3c:93:b5:99,可执行

$ sudo ifconfig en1 ether 00:1f:3c:93:b5:99

来临时修改网卡的物理地址;若没有物理地址,只是想临时启用尝试一下,可用 openssl 生成一个随机的物理地址:

$ openssl rand -hex 6 | sed 's/\(..\)/\1:/g; s/.$//'

当然,用 openssl 生成的物理地址可能会与网络中的网卡地址有冲突,在启用随机生成的网卡地址之前,最好先确认一下是否已有 IP 地址绑定该物理地址:

$ arp -a

2、主机名、计算机名的重置

默认的主机名让人非常无语,特别是出现了一些与 locale 有关的特殊字符。通常情况下,这些并不可见,但是,频繁使用终端时,就会被这些莫名其妙的主机名恶心到了。因此,修改主机名成了当务之急,不过修改的方法很简单。顺次点击左上角的苹果图标->系统偏好设置->共享,接着修改主机电脑名与局域网主机名即可。话说回来,Unix 的命令行是强大的,因此,主机名与计算机名的修改也可以通过命令行修改。

$ sudo scutil --set ComputerName newnameformacosx
$ sudo scutil --set HostName newhostnameformacosx

好了,查看一下修改是否成功:

$ scutil --get ComputerName
$ scutil --get HostName

将主机名放入 /etc/hosts 文件

$ echo 127.0.0.1 newhostnameformacosx >> /etc/hosts

重启网络服务让上述修改立马生效:

$ sudo dscacheutil -flushcache
$ sudo killall -HUP mDNSResponder

3、命令行下载工具的使用

众所周知,wget 是大多数 *nix 系统中标准的命令行下载工具。不过 Mac OS X 中并不自带 wget,取而代之的是命令行下载工具 curl。下面来介绍一下 curl 的基本用法,例如直接下载

$ curl -O http://wordpress.org/latest.zip

若想将下载文件重命名

$ curl -o wordpress-3.8.zip 'http://wordpress.org/latest.zip'

若想在下载过程中显示进度,可执行

$ curl -# -O http://wordpress.org/latest.zip

如果下载的 url 链接需要重定向,可试试下述方式

$ curl -L -o 'file.zip' 'http://example.com/download.php?fileID=foo'

若想节省带宽,可执行

$ curl -L -O --compressed 'http://example.com/large.report-tab.html'

若下载链接需要输入用户名与密码,可试试

$ curl -O ftp://james:123456@202.121.137.58:21/path/to/backup.tar.gz
$ curl -O http://james:123456@202.121.137.58/file/path/data.tar.gz

若下载的是带加密的链接,例如下载链接由 SSL/HTTPS/SFTP 提供,可试试

$ curl --ftp-ssl -u james:123456 -O ftp://202.121.137.58:21/backups/07/07/2012/mysql.blog.sql.tar.gz
$ curl -u james -O sftp://202.121.137.58/backups/data.tar.gz

实际上,curl 也可以上传文件,例如

$ curl -T wordpress.zip ftp://james:123456@202.121.137.58/path/to/backup/
$ curl -T data.tar.gz -u james sftp://202.121.137.58/

若想断点续传,可试试

$ curl -C - -u james -O sftp://202.121.137.58/backup.tar.gz
$ curl -C - -O http://202.121.137.58/file/path/data.tar.gz
$ curl -C - -u james -T data.tar.gz sftp://202.121.137.58/

4、系统更新与 Xcode.app 的命令行工具安装

通常,Mac OS X 上的软件更新是通过 App Store 完成,但是对于那些 geek 来说,可以试试下述命令:

$ sudo softwareupdate --list

会列出所有可能的更新,然后选择需要的更新进行安装

$ sudo softwareupdate --install SomeApp

若不想选择直接更新所有可能的更新,可执行

$ sudo softwareupdate -i -a

Xcode 是 Apple 推出的集成开发环境,它带有 Apple 改良过的 GCC 版本 llvm-gcc。安装它,非常容易,仅需去 App Store 下载 Xcode.app 即可。不过对于 Unix geek 来说,这是不能让人满意的。因为 Xcode.app 不自带命令行工具,需要单独安装它。在 Xcode 5.0 之前,命令行工具的安装非常简单,仅需打开 Xcode.app,然后点击偏好设置->下载->组件,然后选择 Xcode 命令行工具安装即可。但是自 Xcode 5.0 开始,安装 Xcode 的命令行工具,须在终端执行下述命令:

$ xcode-select --install

二、文件系统的相关操作

1、HFS+ 文件系统的扩展属性

在 Mac OS X 下的 HFS+ 文件系统上,文件经常会被附加上 Mac 专有的扩展属性。比如

$ ls -l
total 0
-rw-r--r--@ 1 daniel  staff  0 16 jul 19:28 1.txt
-rw-r--r--  1 daniel  staff  0 16 jul 19:28 2.txt

会有 @ 标志。这个属性是用户在 Finder 里对文件进行任意操作时就会附加上的。比如右键查看 Get Info,然后在 spotlight commands 里写上几个字再删掉,此时,该文件就会附带有 @ 属性。如果想手动去除掉文件的 @ 属性,可以使用命令 xattr。例如

$ xattr -l 1.txt
com.apple.metadata:kmditemfindercomment
$ xattr -d com.apple.metadata:kmditemfindercomment 1.txt
$ xattr -l 1.txt
$ ls -al 1.txt

此时就没有特殊属性了。

2、文件或文件夹的复制、打包与解包

由于 Mac OS X 文件系统中的扩展属性,若将 Mac OS X 系统中的文件直接用打包并释放到 Linux 系统中会造成莫名奇妙的错误,这就需要处理一下文件在复制、打包过程中的扩展属性。首先,Mac OS X 的 cp 命令有一个选项 -X,用它可在复制过程中忽略这些文件的扩展属性。因此,在打包前,先可复制出一份没有扩展属性的文件包,例如

$ cp -Xr /path/to/src - | tar czvf src.tar.gz -

当然,除去扩展属性之外,通常,文件直接打包作成中还会出现 Mac OS X 系统专有的隐藏文件,例如 _MACOSX、._Filename 与 .DS_Store 等。在打 zip 包时,可使用 -X 选项排除这些文件,例如

$ zip -r -X archive_name.zip folder_to_compress

不过,对于 *nix 系统中专有的打包命令 tar,可就没有 -X 选项这么好的东西了。好在 Mac OS X 还是提供了专门的方法,例如,在打 gzip 包时,可使用如下命令

$ COPYFILE_DISABLE=1 tar -zcvf archive_name.tar.gz folder_to_compress

打 bzip2 包也很简单:

$ COPYFILE_DISABLE=1 tar -jcvf archive_name.tar.bz2 folder_to_compress

对于其他格式的 tar 包照此处理。解包过程相对简单,这里附上一段与解包相关的 Bash 配置:

$ echo "# ignore useless invisible files or extended attributes on Mac OS X for cp and tar
export COPYFILE_DISABLE=true
# extract: Extract most know archives with one command
extract () {
    if [ -f $1 ] ; then
         case $1 in
            *.tar.bz2)   tar xjf $1     ;;
            *.tar.gz)    tar xzf $1     ;;
            *.bz2)       bunzip2 $1     ;;
            *.rar)       unrar e $1     ;;
            *.gz)        gunzip $1      ;;
            *.tar)       tar xf $1      ;;
            *.tbz2)      tar xjf $1     ;;
            *.tgz)       tar xzf $1     ;;
            *.zip)       unzip $1       ;;
            *.Z)         uncompress $1  ;;
            *.7z)        7z x $1        ;;
            *)     echo "'$1' cannot be extracted via extract()" ;;
         esac
    else
         echo "'$1' is not a valid file"
    fi
}" >> ~/.bashrc

3、DMG 格式文件的制作以及 ISO 转换互转

DMG 格式是 Mac OS X 中常用的打包格式,创建 DMG 格式的文件,可直接利用系统自带的磁盘工具(Disk Utils)完成。不过这里稍微介绍一下命令行 hdiutil 的用法。创建 DMG 格式的文件

$ hdiutil create -size 100M -stdinpass -format UDZO -srcfolder folder_to_compress archive_name.dmg

其中可以选用的 DMG 格式有 UDZO(压缩格式,默认)、UDRO(只读格式)、UDBZ(Better compressed image)、UDRW(可读写格式)UDTO(DVD 格式)。若想修改 DMG 文件的大小,可执行

$ hdiutil resize 150M /path/to/the/diskimage

若想修改 DMG 格式中的加密口令,可执行

$ hdiutil chpass /path/to/the/diskimage

挂载 DMG 格式的文件可用

$ hdiutil attach archive_name.dmg

它的挂载点在 /Volumes 目录的同名目录下

$ ls -lah /Volumes/archive_name/

卸载 DMG 文件的方法是:

$ hdiutil eject /Volumes/archive_name/

将 ISO 格式的文件转为 DMG 格式的文件

$ hdiutil convert /path/imagefile.iso -format UDRW -o /path/convertedimage.dmg

将 DMG 格式的文件转为 ISO 格式的文件

$ hdiutil convert /path/imagefile.dmg -format UDTO -o /path/convertedimage.cdr
$ hdiutil makehybrid /path/convertedimage.cdr -iso -joliet -o /path/convertedimage.iso

4、文件系统的挂载

大多数情况下,文件管理器 Finder 会自动发现诸如 USB 等外部设备,因此无须用户自行挂载分区;但是,有的时候,例如 Mac OS X 硬盘重新分区后,划出了 msdos 分区或者 ext4 等非 HFS 文件系统的分区,如果要读写这些分区,就需要手动挂载这些文件系统了。挂载文件系统的第一步是建立挂载点,例如

$ sudo mkdir /Volumes/Foo
$ sudo mkdir /Volumes/bar

接着查看有哪些设备需要手动挂载并挂载它们

$ ls /dev/disk*   
$ sudo mount -t msdos /dev/disk1s1 /Volumes/Foo
$ sudo mount -t hfs /dev/disk1s2 /Volumes/bar

最后,卸载这些不在需要的分区

$ diskutil eject /dev/disk1s1
$ diskutil eject /dev/disk1s2

4、文件或文件夹的隐藏属性

通常,为了保护 Mac OS X 系统中的文件不会被用户随意修改,文件管理器 Finder 是不会显示带隐藏属性的文件与系统文件。但是,有些时候,需要操作这些文件(夹), 此时就需要让 Finder 找到这些文件,方法也很简单。在 Finder 的菜单栏中点击 Go -> Go to folder,与之对应的,可使用快捷键 shift+command+G。 当然,如果对于 Mac OS X 自带的文件管理器不满意,可安装第三方文件管理器,例如 totalfinder。其实,单就隐藏文件来说,Mac OS X 还提供了其他方法,下面逐一介绍它们。

4.1 修改 Finder 配置文件

让 Finder 程序显示隐藏文件

$ defaults write com.apple.finder AppleShowAllExtensions TRUE

让 Finder 程序不显示隐藏文件

$ defaults write com.apple.finder AppleShowAllExtensions FALSE

Finder 的配置文件影响到整个文件系统,属于比较暴力的方法。

4.2、开启或关闭某些文件或文件夹的隐藏属性

用下面命令可以解除文件夹的隐藏属性:

$ chflags nohidden ~/Library

恢复文件夹的隐藏属性:

$ chflags hidden ~/Library

事实上,HFS+ 文件系统中文件和目录的隐藏属性也可通过 SetFile 命令来修改。例如,执行

$ mkdir -p ~/Sites
$ SetFile -a V ~/Sites

可开启文件夹 ~/Sites 的隐藏属性;而执行

$ SetFile -a v ~/Sites

可以关闭它的隐藏属性。

三、杂项

1、重置被遗忘的管理员密码

首先,在系统开机还未进入登录界面时按下 command+S 进入单用户模式。然后输入

$ mount -rw /

以读写方式挂载文件系统;接着重置管理员 james 的密码

$ passwd james

完成后,输入

$ reboot

重启开机即可。

2、重建 Spotlight 数据库

比较简单的办法是用鼠标顺次点击系统偏好-> Spotlight ->重建数据库;对于命令行发烧友来说,可以试试

$ sudo mdutil -E /

3、清理缓存

$ sudo purge

Mar 14

Mac OS X 中自带 emacs 与 vi 等编辑器,不过这些编辑器只是命令行模式的。换而言之,只能在打开 Terminal.app 等终端应用之后,输入命令行才能用。例如开启 emacs,在由 Terminal.app 提供终端中输入

$ emacs

启动的 Emacs 也只是以文本模式运行在终端环境中。但是对于习惯图形化操作的用户来说,必然会从例如 http://emacsformacosx.com 等网站下载安装 Emacs for Mac OS X 之类的图形化 Emacs,这些应用一般会提供一个名为 Emacs.app 的程序文件,只需要将该文件拖入 /Applications 文件夹即可完成安装。打开它们的办法如同打开 Terminal.app 一样,只需在 Launchpad 中点击 Emacs.app 对应的图标。 那么如何在命令行中开启图形化的 Emacs 呢?这就需要用到 Mac OS X 提供的命令行 open 了。更准确地说,若要在终端打开由 Emacs.app 提供的图形化 Emacs,可执行

$ open -a /Applications/Emacs.app

它本质上与

$ /Applications/Emacs.app/Contents/MacOS/Emacs

是一样的。此种方式打开的 Emacs 与在 Launchpad 中点击应用图标别无二致。另外,命令行 open 还能传递一些参数到 Emacs.app,例如很多时候,Emacs 的配置文件有问题,需要调试,通常需要将参数 --debug-init 传给 Emacs,若直接在终端执行

$ emacs --debug-init

恐怕启动的并非是我们需要的 Emacs.app。为此,可执行

$ open -a /Applications/Emacs.app --args --debug-init

当然,若不嫌弃繁复的命令,也可

$ /Applications/Emacs.app/Contents/MacOS/Emacs --debug-init

其实,open 还有更多的功能,例如,还想多打开一个图形化 Emacs 实例,可执行

$ open -n /Applications/Emacs.app

为了免去命令行中每次输入那么多参数才能启动图形化 Emacs 的麻烦,建立 alias 是一个方法,例如

$ echo alias emacs='open -a /Applications/Emacs.app "$@"' >> ~/.bashrc

但是缺点也是显而易见的。下面介绍另一种图形化 Emacs 的打开方法,能够弥补 alias 的不足。先在家目录下建一个可执行文件目录,例如 ~/.local/bin,然后做一个 Bash 封装脚本:

$ mkdir -p ~/.local/bin
$ echo "#!/bin/bash
exec /Applications/Emacs.app/Contents/MacOS/Emacs $*" > ~/.local/bin/emacs
$ echo "#!/bin/bash
exec /Applications/Emacs.app/Contents/MacOS/bin/emacsclient --alternative-editor='' $*" > ~/.local/bin/emacsclient
$ chmod +x ~/.local/bin/emacs{,client}

由于启动的是图形化程序,需要将 ~/.local/bin 路径加至 PATH 变量以及 ~/.MacOSX/enviroment.plist,例如

$ cat >> ~/.bash_profile << EOF
export PATH=~/.local/bin:$PATH

## Enviroment Variables for GUI Apps
if [ ! -e $HOME/.MacOSX/environment.plist ]; then
	if [ ! -d $HOME/.MacOSX ]; then
		mkdir -p $HOME/.MacOSX
	fi
	touch $HOME/.MacOSX/environment.plist
fi
defaults write $HOME/.MacOSX/environment.plist PATH "$PATH"
EOF

这样便实现了 Emacs.app 替代 Mac OS X 自带命令行 emacs,也能在其他应用中直接调用 Emacs.app。

Mar 1

如果您喜欢对邮件使用GPG加密或者签名的话,那么GPGMail就是Apple Mail上实现该功能的插件。目前官网上只有针对Mac OS 10.7及以下的版本GPGMail。对于ML上的用户来说,这未尝不是遗憾。不过,最新消息是官方正在测试新版本,我特来给大家提供一个尝鲜的办法。

首先,要通过链接https://nightly.gpgtools.org/GPGTools_Installer-108n.dmg下载并安装GPGTools随后打开它并根据Apple Mail的帐号生成自己需要的GPG密匙。接着,利用Xcode编译最新的GPGMail源码,做法如下。打开终端输入:

$ cd
$ git clone --recursive https://github.com/GPGTools/GPGMail -b experimental

GPGMail的最新源码已位于~/GPGMail目录。下面就是编译它:

$ cd GPGMail
$ make

或者打开Xcode进行编译。如果一切正常的话,会告知编译成功。GPGMail插件就在~/GPGMail/build/Release目录,只要将它复制到~/Library/Mail/Bundles目录,执行

$ cd ~/GPGMail/build/Release
$ cp -r GPGMail.bundle ~/Library/Mail/Bundles

或者鼠标操作均可以。

好啦,现在重启Apple Mail试试吧。
Jan 9

Mac OS X的使用过程中,经常会发生右键快捷菜单条目重复,甚至包含一些已经不存在的软件版本。下图便是一例:

右键菜单中包含了两个版本的TextMate,这让人特别烦恼。究其原因,可能是MacOSX在升级软件过程中,没有更新快捷菜单的数据库。为了解决这个问题,仅需在终端执行

$ /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user

运行结束之后,我们可以从下图中看到右键快捷菜单已经正常:

以上操作在Mac OS X 10.8中能够操作成功。
Nov 8

不知道出于什么原因,比较经典的 CJK 宏包在 MacTeX 2012 中基本被丢弃。但是,我们可能会有一些用 CJK 宏包写的相对古老的 GBK 文档。很明显,与其逐个修改 LaTeX 文档,倒不如修改 MacTeX 来得一劳永逸。下面就来谈谈如何让 CJK 宏包工作起来?  

首先,MacTeX 中已包含了 CJK、Zhmetrics 等处理中文的宏包,只不过它们主要被用作 CTeX 宏包的 XeLaTeX 组成部分;自身的功能则被肢解了,现在就来给出我们的还原方法。

想让 CJK 宏包使用系统字体,需要将系统的字体目录路径写入 OSFONTDIR 变量。通常,我们可以在 TEXMFHOME 树中的 texmf.cnf 文件中修改该变量,具体如下:
$ cd /usr/local/texlive/2012/
$ nano -w texmf.cnf
修改 OSFONTDIR 为
OSFONTDIR = /Library/Fonts//;/System/Library/Fonts//;~/Library/Fonts//
接着需要为 CJK 宏包的相关字体增加对应的字体 map 文件。由于我们要使用 LaTeX 编译文件,因此,需要为 ttf2pk、dvipdfmx 增加 map 文件,这些文件本身就在 MacTeX 之中,我们只需要把它们找出来作适当的修改即可。作如下操作:
$ mkdir ~/Library/texmf/dvipdfmx/
$ cp /usr/local/texlive/2012/texmf-dist/dvipdfmx/dvipdfmx.cfg ~/Library/texmf/dvipdfmx/dvipdfmx.cfg
打开该文件并去掉下面这行的注释符号(%):
$ nano -w ~/Library/texmf/dvipdfmx/dvipdfmx.cfg
f  cid-x.map
还需要修改 cid-x.map,并在其中增加中易公司字体的内容:
$ cp /usr/local/texlive/2012/texmf/fonts/map/dvipdfmx/cid-x.map ~/Library/texmf/fonts/map/dvipdfmx/cid-x.map
$ cat cid-x.map | grep -i sim
%%    The remap option [-r] is simply ignored.
gbk@UGBK@ unicode :0:simsun.ttc -v 50
gbksong@UGBK@ unicode :0:simsun.ttc -v 50
gbkkai@UGBK@ unicode simkai.ttf -v 70
gbkhei@UGBK@ unicode simhei.ttf -v 150
gbkfs@UGBK@ unicode simfang.ttf -v 50
gbkli@UGBK@ unicode simli.ttf -v 150
gbkyou@UGBK@ unicode simyou.ttf -v 60
unisong@Unicode@ unicode :0:simsun.ttc -v 50
unikai@Unicode@ unicode simkai.ttf -v 70
unihei@Unicode@ unicode simhei.ttf -v 150
unifs@Unicode@ unicode simfang.ttf -v 50
unili@Unicode@ unicode simli.ttf -v 150
uniyou@Unicode@ unicode simyou.ttf -v 60
gbksongsl@UGBK@ unicode :0:simsun.ttc -s .167 -v 50
gbkkaisl@UGBK@ unicode simkai.ttf -s .167 -v 70
gbkheisl@UGBK@ unicode simhei.ttf -s .167 -v 150
gbkfssl@UGBK@ unicode simfang.ttf -s .167 -v 50
gbklisl@UGBK@ unicode simli.ttf -s .167 -v 150
gbkyousl@UGBK@ unicode simyou.ttf -s .167 -v 60
unisongsl@Unicode@ unicode :0:simsun.ttc -s .167 -v 50
unikaisl@Unicode@ unicode simkai.ttf -s .167 -v 70
uniheisl@Unicode@ unicode simhei.ttf -s .167 -v 150
unifssl@Unicode@ unicode simfang.ttf -s .167 -v 50
unilisl@Unicode@ unicode simli.ttf -s .167 -v 150
uniyousl@Unicode@ unicode simyou.ttf -s .167 -v 60

剩下来还需要为 ttf2pk 增加 map 文件。这个很简单,只需要从 MacTeX 中复制文件即可:

$ mkdir -p ~/Library/texmf/fonts/map/ttf2pk/config
$ cp /usr/local/texlive/2012/texmf-dist/source/fonts/zhmetrics/ttfonts.map ~/Library/texmf/fonts/map/ttf2pk/config/ttfonts.map 
为了让 MacTeX 系统能够找到我们修改过的文件,通常都需要刷新目录树数据文件:
$ mktexlsr
$ updmap
 
最后,为了确保字体文件能被找到,请打开字体册 FontBook,查看中易六套字体文件。如果没有的话,请安装 MS Office for Mac;当然,也可以在获得使用这些字体的授权之后,将它们从 Windows 系统复制到 Mac OS 的字体目录 /Library/Fonts 或~/Library/Fonts中。
 
为了说明我们的修改已经成功,现做如下的测试文件,打开 TeXShop,并录入下面的内容: 
%!TEX TS-program = latex
%!TEX encoding = GBK

%% test.tex
%% a sample file for testing CJK Package

\documentclass{article} 
\usepackage{CJK} 
\begin{document} 
\begin{CJK*}{GBK}{song} 
你好!
\end{CJK*}
\end{document}
在 TeXShop 中点击 typeset 按钮,大功告成。