LoginSignup
0
0

More than 3 years have passed since last update.

pipで導入したスクリプトがcommand not foundで動作しなかった

Last updated at Posted at 2020-12-24

発端

Mac環境で.msg形式でファイルに保存されたメールを読みたかった。自身に添付ファイルつきメールを送付する方法では読めなかったため、msg-extractorを導入した。

pipでインストールしてから実行したところ、へんじがない。

$ extract_msg 
pyenv: extract_msg: command not found

結論

  • pyenvから呼ぶエントリポイントスクリプトである~/.pyenv/versions/anaconda3-5.3.1/bin/extract_msgに実行権限がついていなかった
  • さらに~/.pyenv/versions/anaconda3-5.3.1/bin/extract_msgの改行コードがCRLFだった

これらを修正したところ正常に動作するようになった。ツールとしては大変満足で、エクセルやpngの添付ファイルまで分離してくれました。

問題判別の試行錯誤

原因の特定まで時間を溶かしたため、脳内ダンプを兼ねて調査の流れを記録に残す。

pipでインストールされた内容を確認する

$ pip show extract-msg
Name: extract-msg
Version: 0.27.9
Summary: Extracts emails and attachments saved in Microsoft Outlook's .msg files
Home-page: https://github.com/TeamMsgExtractor/msg-extractor
Author: The Elemental of Destruction & Matthew Walker
Author-email: arceusthe@gmail.com, mattgwwalker@gmail.com
License: GPL
Location: /Users/haruyosh/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packages
Requires: compressed-rtf, olefile, imapclient, tzlocal
Required-by: 
  • /Users/haruyosh/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packagesextract_msg/extract_msg-0.27.9.dist-info/が存在する
  • extract_msg/には__main__.pyが存在する
  • __main__.pyを生で呼び出すと正しく動作する

少なくとも生スクリプトは動作することが分かったので、呼び出し元から一つずつ皮を剥いていくことにする。

スクリプトを見ていく

どこにあるのか、内容はどうなっているのか。まず1段目に呼び出しているのは次のスクリプト。

$ which extract_msg
/Users/haruyosh/.pyenv/shims/extract_msg

後で気づいたことだが、~/.pyenv/shimsにあるスクリプトはラッパースクリプトの扱いで、全て同一内容(っぽい)。

$ ls -l ~/.pyenv/shims/ | head -6
total 2896
-rwxr-xr-x  1 haruyosh  staff  418  9 16 13:53 2to3
-rwxr-xr-x  1 haruyosh  staff  418  9 16 13:53 2to3-3.7
-rwxr-xr-x  1 haruyosh  staff  418  9 16 13:53 Assistant.app
-rwxr-xr-x  1 haruyosh  staff  418  9 16 13:53 Designer.app
-rwxr-xr-x  1 haruyosh  staff  418  9 16 13:53 Linguist.app

正常動作しているipythonと比べておく。同一内容。

$ diff ~/.pyenv/shims/{extract_msg,ipython}
$

この同一内容であるスクリプトの中身を見ると、ファイル末尾に実行内容が書いてあった。

$ tail -4 `which extract_msg`
fi

export PYENV_ROOT="/Users/haruyosh/.pyenv"
exec "/usr/local/Cellar/pyenv/1.2.20/libexec/pyenv" exec "$program" "$@"

さらに実行先ファイルの中を見てみると、デバッグオプションがあることが分かった。

$ head -8 /usr/local/Cellar/pyenv/1.2.20/libexec/pyenv
#!/usr/bin/env bash
set -e

if [ "$1" = "--debug" ]; then
  export PYENV_DEBUG=1
  shift
fi

デバッグオプションをつけて実行し、正常動作しているipythonと今回動作させたいextract_msgの出力を突合する方針にした。

$ PYENV_ROOT="/Users/haruyosh/.pyenv" /usr/local/Cellar/pyenv/1.2.20/libexec/pyenv --debug exec extract_msg 2> extract_msg.stderr
$ PYENV_ROOT="/Users/haruyosh/.pyenv" /usr/local/Cellar/pyenv/1.2.20/libexec/pyenv --debug exec ipython 2> ipython.stderr

比較して見ていくと、145行目まで同一内容だった。しかし146行目、ipythonはbreakして抜けているところ、extract_msgにはbreakが記録されていない。
image.png

その時点で実行されていたpyenv-whichの該当箇所を見てみる。

$ less -N /usr/local/Cellar/pyenv/1.2.20/libexec/pyenv-which
:
     49   if [ -x "$PYENV_COMMAND_PATH" ]; then
     50     break
     51   fi
:

ここでは渡したスクリプトの実行権限を見ている。extract_msgには実行権限がなくてbreakしなかったということになる。実際に見てみると確かにextract_msgに実行権限がない!

$ ls -l ~/.pyenv/versions/anaconda3-5.3.1/bin/{extract_msg,ipython}
-rw-r--r--  1 haruyosh  staff   74 12 24 17:12 /Users/haruyosh/.pyenv/versions/anaconda3-5.3.1/bin/extract_msg
-rwxr-xr-x  1 haruyosh  staff  270  5 17  2019 /Users/haruyosh/.pyenv/versions/anaconda3-5.3.1/bin/ipython

ここまででビンゴだと思ったがぬか喜びだった。実行してみるがさらにダメ。

$ chmod +x ~/.pyenv/versions/anaconda3-5.3.1/bin/extract_msg 
$ extract_msg 
env: python\r: No such file or directory

'\r'ってなんなのよもう。でも進研ゼミでやったやつだ

$ od -c ~/.pyenv/versions/anaconda3-5.3.1/bin/ipython | head -4
0000000    #   !   /   U   s   e   r   s   /   h   a   r   u   y   o   s
0000020    h   /   .   p   y   e   n   v   /   v   e   r   s   i   o   n
0000040    s   /   a   n   a   c   o   n   d   a   3   -   5   .   3   .
0000060    1   /   b   i   n   /   p   y   t   h   o   n  \n  \n   #    
$ od -c ~/.pyenv/versions/anaconda3-5.3.1/bin/extract_msg | head -4
0000000    #   !   /   u   s   r   /   b   i   n   /   e   n   v       p
0000020    y   t   h   o   n  \r  \n  \r  \n   f   r   o   m       e   x
0000040    t   r   a   c   t   _   m   s   g   .   _   _   m   a   i   n
0000060    _   _       i   m   p   o   r   t       m   a   i   n  \r  \n

こうして、こうじゃ

$ tr -d '\r' < extract_msg > extract_msg.new
$ mv extract_msg extract_msg.old
$ mv extract_msg.new extract_msg

動くかな?

$ extract_msg 
pyenv: extract_msg: command not found

おっと。そうだね

$ ls -l extract_msg*
-rw-r--r--  1 haruyosh  staff  69 12 24 18:04 extract_msg
-rwxr-xr-x  1 haruyosh  staff  74 12 24 17:12 extract_msg.old

これでどうじゃ

$ chmod +x extract_msg

動いた!

$ extract_msg 
usage: extract_msg [-h] [--use-content-id] [--dev] [--validate] [--json]
                   [--file-logging] [--verbose] [--log LOG]
                   [--config CONFIG_PATH] [--out OUT_PATH] [--use-filename]
                   [--dump-stdout]
                   msg [msg ...]
extract_msg: error: the following arguments are required: msg
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0