ラベル shell の投稿を表示しています。 すべての投稿を表示
ラベル shell の投稿を表示しています。 すべての投稿を表示

2013年2月5日火曜日

MANPATH環境変数の整理

PATH環境変数の記事を書いている時に、自分のMANPATHもあまり整理されていないことに気づいたので、それについても書きたいと思います。

MANPATHは、Unixコマンドや関数の使い方の説明マニュアルであるmanページを探すための環境変数です。manページはターミナル上でmanコマンドを使い見ることができます。
例えば、grepコマンドについて知りたいと思ったら、
$ man grep
と、ターミナル上のプロンプトから入力すれば、以下のような説明が出てきます。

GREP(1)                                                                GREP(1)

NAME
       grep, egrep, fgrep - print lines matching a pattern

SYNOPSIS
       grep [options] PATTERN [FILE...]
       grep [options] [-e PATTERN | -f FILE] [FILE...]

DESCRIPTION
       Grep  searches the named input FILEs (or standard input if no files are
       named, or the file name - is given) for lines containing a match to the
       given PATTERN.  By default, grep prints the matching lines.

       In addition, two variant programs egrep and fgrep are available.  Egrep
       is the same as grep -E.  Fgrep is the same as grep -F.

OPTIONS

... 長いので以下省略します...

元に戻ってMANPATHについての話です。

MANPATHは、manコマンドがmanファイルを探す場所を指定します。基本的な考え方としては、PATH変数と同じように、特殊・ローカルなディレクトリを先に、標準のディレクトリを後に指定すればよいと思います。また、PATH変数で指定されるディレクトリには、対応するman ファイルのディレクトリがありますので、PATHに合わせて指定すればよいでしょう。
現在の私のMANPATHは以下のようになっています。実は、整理した結果こうなったのですが、整理前は、/usr/local/manなどが複数回現れたり後ろの方に来ていました。

/Users/karuku/local/man:/Users/karuku/local/share/man:/usr/local/share/man:/opt/local/man:/usr/share/man:/opt/X11/share/man:/usr/local/clamXav/share/man

それぞれ以下に説明します。

/Users/karuku/local/man - ~/local/{bin,sbin}に対応します
/Users/karuku/local/share/man - 同上。上のものと合わせる方がよいのかも
/usr/local/share/man - /usr/local/{bin,sbin}に対応します
/opt/local/man - MacPorts用のman。/opt/local/share/manへのリンク
/usr/share/man - /usr/{bin,sbin}, /{s}binに対応します
/opt/X11/share/man - /opt/X11/binに対応します
/usr/local/clamXav/share/man - ClamXav用のman

ところで、同じディレクトリで、…/manとなっていたり、…/share/manとなっていたり、両方ある場合があります。
私の理解では、以前は、.../manというように…/binディレクトリと同じ階層にmanディレクトリのみが作られていたと思います。それが、いつの頃からか…/share/manに変更されてきたようです。…/share/manを知らないコマンドのために…/manも残されていた、または、…/share/manへのシンボリックリンクになって併存した時代が続き、最近は、…/share/manに統一されてきているようです。
OS Xの場合は、システムディレクトリは、…/share/manになっているようですね。

また、PATHとMANPATHで少し違うところがあります。PATHはコマンドの実行用なので最初にPATHの中から見つかったコマンドがシェルによって実行されます。
でも、MANPATHの場合は、manコマンドでマニュアルを見るためのものなので同名のコマンドや関数が重なっても、最初に見つかったものではないものを見たい場合があります。
その場合は、以下のようにmanコマンドに -a オプションを付ければすべての同名のコマンドや関数のファイルを表示してくれます。

例えば、md5コマンドについて知りたい場合、
$ man -a md5
とすると、私の場合は、openssl dgstコマンドのサブコマンドのmd5, /sbin/md5, md5関数、Tclでサポートされているmd5などの説明が表示されます。

皆さんも、ときどきPATHやMANPATHその他の環境変数を確認されるとよいのではないでしょうか。

2013年1月29日火曜日

PATH環境変数内の、~/bin, /bin, /usr/bin, /usr/local/binなどの順番

ターミナルでシェルを使う場合の小ネタです。初心者には重要かもしれません。知っている人は今さらと思うかもしれませんが。
私は、以前はtcshを使っていました。Mac OS X 10.6.2までターミナルのデフォルトのシェルだったからです。Tiger (10.6.4)の時からbashにしました。乗り換えが1世代遅れたのは、使い方に若干慣れないところがあったのと、.tcshrcから.bashrc, .bash_profileへの変更が面倒だったためです。シェルスクリプトは/bin/shで書くことにしています。

今回の本題は、tcsh, bashのどちらにも関係するのですが、PATH環境変数内に設定するディレクトリの順番です。別の考え方もあると思いますので、参考ということで。

PATH環境変数は、コマンドを探すときのディレクトリの順番を指定するものです。PATH変数に含まれていないディレクトリにあるコマンドを指定しても、"コマンドが見つかりません"といったエラーがでます。

$ chdir
-bash: chdir コマンドが見つかりません

ディレクトリにコマンドが存在するのに上のようなエラーが出る時は、PATH環境変数にそのディレクトリが含まれていない(PATHが通っていないと言いますね)か、そのコマンドに実行権がないか、csh系だとrehashしていないという場合が多いです。(自分の経験では)

現在の私のPATH環境変数は、以下のようになっています。

$ echo $PATH
/Users/karuku/bin:/Users/karuku/local/bin:/usr/local/bin:/opt/local/bin:/usr/local/sbin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/local/clamXav/bin

基本的な考え方は、特殊なもの、局所的なものを先頭に持ってくる、標準的なものは後ろにするというふうにしています。一部、その考え方に沿っていないところもありますが。

定義順にそれぞれの使用目的を書いてみます。

/Users/karuku/bin - ホームディレクトリ下のbinです。自分で作成したスクリプト類を置いています
/Users/karuku/local/bin - テスト目的でインストールしたいものを置いています
/usr/local/bin - MacPortsでサポートされていないコマンドを置いています
/opt/local/bin - MacPortsでサポートされているコマンドを置いています
/usr/local/sbin - MacPortsでサポートされていないシステムコマンドを置いています
/opt/local/sbin - MacPortsでサポートされているシステムコマンドを置いています
/usr/bin - 一般的なユーティリティ、プログラミングツール、アプリケーション
/bin - ユーザ用ユーティリティの基本的なもの。シングルユーザ環境、マルチユーザ環境どちらでも使用する
/usr/sbin - (ユーザによって実行される) システムデーモン、およびシステムユーティリティ
/sbin - (ユーザによって実行される) システムデーモン、およびシステムユーティリティ
/opt/X11/bin - XquartzでインストールされるX Window System
/usr/local/clamXav/bin - ウィルスチェッカー clamav / clamXavをインストールしています。

( /binや/usr/binなどのシステムディレクトリ説明にはjman hierの記述を使いました。)

最後のふたつの /opt/X11/binと/usr/local/clamXav/binは、最初の考え方の原則に反していますね。

/opt/X11/bin (X11)は、Xquartsをインストールした際に、/etc/paths.dに登録されました。ここに登録されると、ログイン時に/etc/profile内で、その時のPATH変数にアペンドされる形になるようです。
X11は、以前Mac OS Xに使いたいGUIアプリケーションが少なかったころや、会社でLinuxマシンを使う際に使っていましたが、最近は全く使っていません。LinuxかFreeBSDを使うこともなさそうなので、当面このままにするつもりです。

clamXavは、ターミナルからではなく、Finderから使う場合がほとんどなので、PATHから外してもいいかもしれないですね。

コマンド名がぶつかる場合

たまに、同名のコマンドがそれぞれのディレクトリにある場合があります。上の考え方の場合、通常は使いたいコマンドが先に来ているので問題ないのですが、たまに後のディレクトリのコマンドをデフォルトとして使いたい場合があります。
例えば、rsyncはAppleの提供しているバージョンとMacPortsでインストールされるバージョンでは、HFS+関係の属性等を扱うオプションが違います。MacPortsのrsyncを使おうと思った訳ではなく、依存関係でインストールされたのですが。

こういう場合は以下のようにしています。

シェルスクリプトの場合は、以下のようにフルパスで記述します。

RSYNC=/usr/bin/rsync
RSYNC -hfsv ...

コマンドラインから使う場合は、~/bin から使いたいバージョンのコマンドにシンボリックリンクを張ります。~/binは先頭にあるので、意識せずに使いたいバージョンのコマンドが使えます。

$ ln -s /usr/bin/rsync ~/bin

別の解決方法として、alias が考えられますがあまり使っていません。特に意識していませんでしたが、bashの場合、whichコマンドでaliasで定義したコマンドが表示されないから(方法を知らないだけかもしれませんが)というような理由です。
また、bashに移行した初めの頃は、tcshも併用していたので、~/binの一箇所に設定しておけばいいからという理由もあったかもしれません。(ちょっとうろ覚えです)

2012年9月30日日曜日

ファイルを探すコマンド

Finderの「このアプリケーションで開く」その2や、locateデータベースを作る方法の中でlocateコマンドでファイルを探す記事を書きました。自分の場合、どのようにファイルを探したり思い出したりするのにどんな方法を使っているか主なところを書いてみます。この記事ではターミナルというかシェル(bash)を使う場合について書いています。

次の3つの使用場面で分けてみました。(1) 現在のディレクトリ内を探したい場合、(2) 現在または特定のディレクトリとそのサブディレクトリ含めて探したい場合、(3) コマンド名を探したい場合の3つです。

(1) まず、はじめは、現在のディレクトリ内ですね。
lsコマンドを使う場合が多いです。普通すぎますね。lsコマンドは、現在自分のいるディレクトリや、指定したディレクトリのファイル名を表示します。よく使うのは、単純な
$ ls
と、作成時間の順に表示する
$ ls -lt (または $ ls -ltr )
です。
-ltオプションは、ファイルの変更時間が新しい順に表示します。-ltrオプションのように-rを追加すると古い順に表示します。最近使ったファイル名をしりたい場合が多いので、-rを指定すると次のコマンドプロンプトの近くにファイル名が表示されて便利です。-rを使わないと、最近のファイルが画面からスクロールアウトしてしまう場合も多いですしね。
ファイルが多い場合は、lessやhead, tailで画面外に出ないようにすることもあります。
また、多少ファイルが多い場合は、ls a*.html のようにワイルドカードで一部を指定したりすることもあります。
同じディレクトリ内ですと、ほとんどlsで用が足りますね。

(2) 次は、現在ディレクトリとそのサブディレクトリすべて、またはあるディレクトリとそのサブディレクトリ以下をすべて探す場合です。現在いるディレクトリや特定のディレクトリの場合は、findコマンドを使う場合が多いですがlocateコマンドも使います。
$ find . -name "*foobar*"
上のfindコマンドの場合は、"."は、カレントディレクトリを示すので、現在のディレクトリ以下から探すことを意味し、-nameコマンドでファイル名の一致条件を指定します。この場合は、ファイル名の一部に"foobar"を含むファイルを探して表示します。ファイル名の大文字、小文字の区別をしない場合は、-inameオプションが使えます。
また、ファイル名の代わりにディレクトリ名を探す場合は、次のように-type dを追加します。
$ find . -type d -iname "application*"
探したいファイルが、特定のディレクトリの下にあるとわかっている場合は、例えば
$ find /opt/local -name "a*.conf"
のようにするか、そのディレクトリに移動後(cd /opt/local)、探したいパス名の部分に"."を指定しています。後でフルパス名を使いたい場合が多いので、初めの方法をよく使います。
findコマンドは他にも時間指定したり、見つかったファイルに対して処理を行うオプションなどがあるので調べると面白い使い方が出来ると思います。

locateコマンドは、ファイルがどこにあるかわからない場合や、findコマンドで探すとディレクトリ階層の上位(/に近い場合)で、その下にファイルが大量にある場合、まず、locateコマンドを使ってみるという使い方が多いです。使い方は、単純に
$ locate "ファイル名の一部"
とすることが多いです。
locateコマンドはfindコマンドに比べスピードが速いのですが、

  • データベースを作っておく必要があります。
  • データベースは、設定にもよりますが一週間に一回しか更新されないので最近作成したファイルは見つけられません。
  • 検索する単語が短かかったり、パス名の上の階層に一致する場合は出力が多すぎて、そこからさらに絞り込まないといけない場合が結構あります。
  • Macを個人で使っている場合はあまり関係ないかもしれませんが、サーバーのように他の人も使う場合、他のユーザからファイル名が見られてしまうというセキュリティ上の問題があります。

といったことを注意しておく必要があります。
実行ファイルのコマンド名を忘れた場合に限られますが、which、

(3) 最後の場合として、コマンド名を探す場合です。
よく使うのは、whichコマンドです。
$ which curl
などのように、コマンド名を指定します。シェルがbashの場合、whichコマンドは、現在指定しているPATHに従って有効なコマンドのパス名を表示します。例えば、/usr/localの下やMacPortsを使って標準以外の場所にも、標準と同名のコマンドをインストールしている場合、どれが使われているかを確認できます。
気をつけないといけないのは、実際はbashのビルトインコマンドを使っている場合やaliasで既存のコマンドと同じ名前でコマンド名を置き換えていても、ファイルシステム上に見つかったコマンドしか表示されない点です。私の環境で、cdとh、aaaを指定した場合ですが、以下のようになります。
$ which cd
/usr/bin/cd # whichの出力です
$ which h
$ # 何も表示されません。
$ which aaa
$ # 何も表示されません。
でも、実際は、cdは、bashの内部に組み込まれているcdコマンドが使われています。また、lsもalliasコマンドで、h='history | tail -40 | more'と設定しています。
最近はbashを使っているのですが、以前使っていたtcshでは、
% which cd
cd: shell built-in command.
% which h
h: aliased to history 25
% which aaa
aaa: Command not found.
のように、実際に使っているコマンド(historyもシェル組み込みコマンドです)が表示されます。見つからない場合も見つからないと表示されます。

また、which コマンドの引数には探したいコマンド名をフルネームで指定しないと結果が表示されないので、コマンド名を忘れていると使えないですね。
コマンド名を覚えておかないといけない欠点をカバーする方法として、bashの組み込みコマンドcompleteがありますね。コマンド名やファイル名の先頭部分を入力して、覚えている場合に、lsで始まるファイル名の候補を示してくれます。以下は、コマンドプロンプトに、which lsと入力し、tabキーを押した場合の表示です。
$ which ls[tab]

ls        lsdistcc  lsm       lsof      
lsbom     lslen.sh  lsmac     lsvfs
$ which ls
ここで、表示を見ながら入力を継続したり、例えば"v[tab]"と入力すると、lsvfsまで補完
してくれます。
$ which lsv[tab] # tabキーを押した瞬間、次の行のように表示されます。
$ which lsvfs
ファイル名を探す場合より、入力を結構便利です。
長くなったのでこのあたりで終わります。また、関連した話題を書きたいとおもいます。

2012年9月22日土曜日

ターミナルから無圧縮ZIPファイルを作る

少し前の記事で、Automatorでシェルスクリプトを実行するという内容の記事がありましたが、無圧縮ZIPファイルをどのようなコマンドで作っているか書いていませんでした。その記事へのアクセスが結構多いようですので、実際にZIPファイルを作っている部分を書いてみます。エラーチェック等は省略して、肝心の部分は以下のような感じになっています。

zip -r -n ".jpg:.JPG:.jpeg:.JPEG:.gif:.GIF" "$zipf" "$zipd" -x ".DS_Store"

-r オプションは、ZIPの入力ファイルにディレクトリがある場合、再帰的にたどっていくことを指示します。
-n オプションは、引数として与えられた拡張子を持つファイルを、圧縮しないように指示します。tiffやpngも入れてもいいかもしれません。大文字小文字の違いを無視できればよいのですが、ちょっと冗長になっています。私は、テキストファイルなどは圧縮したいので、このオプションを使っています。
-nオプションの代わりに、-0オプションを使えばすべてのファイルが無圧縮になります。-# (#は0から9の数字が入ります)の形式のオプションは、圧縮スピードを相対的に指定するのですが、-0は無圧縮の指定になっています。-0の方が無圧縮ファイル作成の目的に合う人はこちらの方がよいと思います。
$zipfは、作成するZIPファイル名が入った変数です。
$zipdは、作成対象のディレクトリ名が入った変数です。両方共ダブルクォーテーションで囲んであるのは、文字列中にスペースがあるとシェルが別々の引数として処理するため、予防的に入れています。
最後の-xオプションは、ZIPの対象としないファイルを指定します。.DS_StoreはFinderが不可視ファイルとして作る場合がありますが、今回はZIPファイルに含める必要はないため除外するようにしています。

zipコマンドの詳細はターミナルからmanコマンドで調べることもできます。

2012年9月15日土曜日

Finderの「このアプリケーションで開く」その3

一応、表題の問題は解決はしたのですが、前回からの続きです。
The Unarchiver以外にも、複数回登録されているアプリケーションがないか、確認してみました。
前回と同じく、lsregisterのあるディレクトリに移動します。

$ cd `dirname \`locate lsregister\``

次のコマンドをターミナルから入れて確認します。

$ ./lsregister -dump | grep "path: .*\.app" | sort | uniq -d


各コマンドの説明をします。
lsregisterの -dump オプションで、Lauch Servicesが使っているデータベースを出力して次のgrepコマンドに渡します。
grepコマンドは、渡された文字列から条件に合う行を探して表示します。ここでは、渡された各行に、path:で始まり.appで終わるパターンがあるかどうかを探しています。path: 〜 .appは行の途中に出てきていてもかまいません。次に、sortコマンドに見つかった結果を渡します。
sortコマンドは、入力された行を順番に(今回の場合アルファベット順)に並び替えて表示します。その結果をuniqコマンドに渡します。
uniqコマンドは、入力から重複している行を探してくれます。uniqコマンドは隣同士の行(1行前の行と現在の行)しか比較しませんので、uniqにgrepの結果を渡す前にsortコマンドで順番に並び替えています。同じ行があれば隣同士になります。uniqコマンドの-dオプションは、重複している行だけを表示します。

結果は次のようになりました。

path:      /Volumes/Disk2/Applications/Flaex.app
path:      /Volumes/Disk2/Applications/GrowlTunes.app
path:      /Volumes/Disk2/Applications/Inkscape.app
path:      /Volumes/Disk2/Applications/OnyX.app
path:      /Volumes/Disk2/Applications/OpenOffice.org.app
path:      /Volumes/Disk2/Applications/Rember.app

同じパスで重複登録されているアプリケーションが6個ありました。あまり使っていないものばかりだったので、今回はそのままにすることにしました。
ところで、今のままですと、例えば起動ディスクと外付けディスクに同じアプリケーションがある場合見つかりません。これは、時間があればスクリプトでも作ってみようかと思います。

2012年9月14日金曜日

locateデータベースを作る方法

このアプリケーションで開く その2の記事で、lsregisterコマンドをlocateコマンドで見つけることができると書きましたが、locateコマンドが使えないというか期待通りに動作しない場合があります。locateコマンドが使うデータベースがまだ存在しない場合です。
Snow Leopardの場合ですが、以下のように表示されます。
$ locate lsregister

WARNING: The locate database (/var/db/locate.database) does not exist.
To create the database, run the following command:

  sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.locate.plist

Please be aware that the database can take some time to generate; once
the database has been created, this message will no longer appear.

簡単に訳すると、
locateコマンドが使うデータベース(/var/db/locate.database)がまだないので、sudo launchctl から始まっているコマンドで作ってと言っています。
これをターミナルで実行すればデータベースが作られます。1行で入力する必要があります。結構時間がかかると注意書きがあります。


launchctlコマンドが、直接locateデータベースを作っているのではなく、launchdというデーモンプロセス(システム上に常駐しているプロセス)に、/System/Library/LaunchDaemons/com.apple.locate.plistファイルに従って動作するように教えています。このファイル中で、locateデータベースを作るコマンドや実行するタイミングなどが定義されています。興味のある人は調べるといいと思いますが、データベースは1週間に一度土曜日の午前3:15に更新されるようです。最近インストールしたファイルはすぐ見つからない場合もあるかもしれません。

2012年7月22日日曜日

ディスクユーティリティでマウント解除できない

前のエントリーで、ディスクユーティリティのマウント解除と再マウントでread onlyのディスクを読み書きできるようにする方法を紹介しました。
これで、再起動しないでTime Machineがバックアップできるようになります。
でも、たまにマウント解除自体ができない場合があります。
例えばこんな感じです。

そこで、再起動しないでマウント解除する方法を模索しました。
ここからは、ターミナルでコマンド操作を行いますので、参考程度に見てください。間違っていても責任はとれませんし。
(1) まず、ディスクがread onlyでマウントされているかの確認ですが、moutコマンドで見ることができます。今回の例です。ちなみに、Mac OS X 10.6.8 (Snow Leopard)です。Developer Toolsもインストールしています。


$ mount
/dev/disk0s2 on / (hfs, local, journaled)
devfs on /dev (devfs, local, nobrowse)
map -hosts on /net (autofs, nosuid, automounted, nobrowse)
map auto_home on /home (autofs, automounted, nobrowse)
/dev/disk1s2 on /Volumes/Backup (hfs, local, nodev, nosuid, read-only)
/dev/disk2s2 on /Volumes/Disk1 (hfs, local, nodev, nosuid, journaled, noowners)

/dev/disk1s2 が、/Volumes/Backup としてread-onlyでマウントされています。


(2) 次に、lsofコマンドとgrepコマンドで、/Volumes/Backup を使っているプロセスを調べます。lsofとgrepは知っていることにします。

$ lsof | grep -F /Volumes/Backup

(3) 例えば、こんな行があったとします。
iTunes     3544  karuku   22r     DIR       14,8       952        2 /Volumes/Backup
この場合は、単純にiTunesを終了させます。

(4) 直接起動していないのに、なにか動いている場合もあります。
stunnel   12083  karuku  cwd      DIR       14,8    204340   203460 /Volumes/Backup/Mail/inbox
stunnel   12083  karuku  txt      REG       14,8    132832  7940984 /Volumes/Backup/opt/local/bin/stunnel

この場合、stunnelが他のアプリケーションから起動されていると知っていれば、その親のアプリケーションを終了させればいいです。

わからない場合は、あきらめてMacを再起動するほうがいいです。特に3つめが自分のログインIDでないものがある場合は、再起動ですね。


そして、(2)、(3), (4)を繰り返して、/Volumes/Backupを使っているプロセスがいなくなれば、ディスクユーティリティからマウント解除が使えると思います。
せっかくターミナルを使っているので、umount/mountコマンドを使ってもいいですけど。

Nerdtool/GeekToolでYahooのお天気アイコンを表示

Macの手書き説明書さんなどを参考に、NerdToolでYahooのお天気アイコンをデスクトップに表示させていたのですが、いつの間にか表示されなくなっていました。

weather.yahoo.comのHTMLコードが修正されているようです。
以下のように修正したらまた表示されるようになりました。


今日はくもりです。

GeekToolを使っている人も同じような修正で、アイコンが表示されるようになると思います。
NerdToolの方がほんのちょっとCPU負荷が低かったのでGeekToolから乗り換えました。と言っても、2%ぐらいですが。
私のMacは、Mac Mini Core 2 Duo 1.83GHzの非力マシンなので。。