macOS Mojaveに更新したらgitコマンドが使えなくなった

macOS Mojaveに更新したらgitコマンドが使えなくなった。

macOSを10.14 Mojaveに更新した。
gitコマンドがエラーになった。

症状:git pullできない

1
2
MacBookAir:program user$ git pull
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

原因:Command Line Toolsが動作しなくなっていた

次のコマンドを実行し、Command Line Toolsをインストールしたら、今まで通り動くようになった。

1
2
MacBookAir:program user$ xcode-select --install
xcode-select: note: install requested for command line developer tools

まとめ

High Sierraに更新したときも同じ症状になっていた。
すっかり忘れていた。
次は、High Mojave(Mojave Max?)のときだろうか。

同じタグの記事
同じカテゴリの記事

jQueryで部分一致検索

jQueryで部分一致検索

誰かの作った難解なプログラムがある。サーバサイドは手がつけられない。
クライアントサイドはjqueryが利用されている。こちらはなんとかなりそう。

クリックイベントが設定されたelementがあり、その同レベルにinputタグがある。そのinputタグを辿りたい。

parent().find()

同レベルなので、親(Parent)を起点に検索(Find)する。

1
$(this).parent().find(xxx)

selector “input[name$=’.lastName’]”

同レベルにある下記の値を取得したい。

1
<input type="text" name="list[0].lastName" value="Doe" />
1
var lastName = $(this).parent().find("input[name$='.lastName']").val()

取得できた。
“$=”は後方一致として動作する。
ちなみに、前方一致は”^=”。
正規表現のようだ。
部分一致は”*=”。これは正規表現ではない。

まとめ

javascriptのみでプログラムを改修することができた。
jquery便利だ。

同じタグの記事
同じカテゴリの記事

macOSをMojaveに更新した。スクリプト実行環境のバージョンは変わったか

macOSをMojaveに更新した。スクリプト実行環境のバージョンは変わったか

Python

Mojave

1
2
3
Python 2.7.10 (default, Aug 17 2018, 17:41:52)
[GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

High Sierra

1
2
3
Python 2.7.10 (default, Oct  6 2017, 22:29:07)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

Pythonのバージョンは変更なし。
コンパイラのバージョンは上がっている。

perl

Mojave

1
2
3
4
This is perl 5, version 18, subversion 2 (v5.18.2) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)

Copyright 1987-2013, Larry Wall

High Sierra

1
2
3
4
This is perl 5, version 18, subversion 2 (v5.18.2) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)

Copyright 1987-2013, Larry Wall

perlのバージョンは変わらない。

PHP

Mojave

1
2
3
PHP 7.1.19 (cli) (built: Aug 17 2018 18:03:17) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies

High Sierra

1
2
3
PHP 7.1.16 (cli) (built: Mar 31 2018 02:59:59) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies

細かいバージョンが上がっている。

Ruby

Mojave

1
ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin18]

High Sierra

1
ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin17]

Rubyのバージョンは変わらない。

sqlite3

Mojave

1
SQLite version 3.24.0 2018-06-04 14:10:15

High Sierra

1
SQLite version 3.19.3 2017-06-27 16:48:08

細かいバージョンが上がっている。

まとめ

今回もPythonのバージョンアップはなかった。
macOSの何らかのプログラムがPython2に依存しているのだろうか。

同じタグの記事
同じカテゴリの記事

Pythonでリスト、タプルの重複除去

Pythonでリスト、タプルの重複除去

特殊なデータストアからデータを抽出し、返却するバッチ処理がある。そのバッチ処理は定期実行され、キューイングはXMLファイル行われる。
同じ時間の処理で、返却先が異なるが同じデータへのリクエストが来ることがある。
同じデータをデータストアに何度もアクセスしたくない。リクエストをListにため込んでから、重複を除去して問い合わせを行う。
Listの重複をどのように行うか。

setを利用する

1
2
3
4
5
6
7
work_list = []
for x in range(10):
    work_list.append(x % 3)
print(work_list)

target_set = set(work_list)
print(target_set)

このプログラムを実行すと、work_listは

1
[0, 1, 2, 0, 1, 2, 0, 1, 2, 0]

target_setは

1
{0, 1, 2}

と出力される。

まとめ

リストの重複除去が簡単に行えた。
しかし、順序は保証されないようなので、順序が重要な場合は自身でイテレートして重複を除去する必要がある。
または、そもそもwork_listにappendする前に、if xx not in work_list:でリストに含まれないことを確認してからappendすればよい。ここはお好みで。

同じタグの記事
同じカテゴリの記事

Linuxコマンドを利用してログを集計する

Linuxコマンドを利用してログを集計する

相変わらず、ログを集計している。
今回は特定の処理を呼ばれたかどうかを集計するだけなので、Pythonスクリプトを作成する必要もない。
日別に何件発生しているのか、集計しようと思う。

最初に結果

1
find . -name 'app.log.20*' | xargs grep -h "my.Program" | cut -b 1-10 | sort | uniq -c | awk '{print $2"\t"$1}' > res.txt

これで日別の件数が取得できた。
パイプで繋がれた、それぞれのコマンドにどのような役割があるのか、以下で説明する。

find

1
find . -name 'app.log.20*'

ログファイルはapp.log.yyyymmddの形式で出力されている。ログディレクトリに保存されているのだが、当月、当年、それより前でディレクトリ構成が異なる。また、異なるシステムのログファイルも含まれているため、事前にファイルの選別が必要になる。それでfindを利用している。

xargs grep

1
xargs grep -h "my.Program"

findの結果をxargsを利用してgrepに通している。
grepでは、見つけたログファイルの中に、特定の文字列(チェック対象のプログラム名)が含まれている行を抽出している。
-hオプションは、grep結果にファイル名が出力されることを抑制するために指定している。

cut

1
cut -b 1-10

grep結果の先頭10バイトは年月日がYYYY/MM/DD形式で書かれている。そこだけを抽出した。

sort

1
sort

次の処理で日別の件数を求めるが、そのコマンドは集計キーが並んでいる必要がある。そのためにcutの結果をsortした。

uniq

1
uniq -c

uniqコマンドで年月日ごとの出力行数をカウントした。
-cオプションが集計数を表示するオプション。
-cオプションが指定されないと、重複行の除去のみ行われる。

awk

1
awk '{print $2"\t"$1}'

uniqの出力結果は”集計件数 集計項目”の順番で出力される。今回の例では下記のように出力される。

1
2
   100 2018/09/01
    98 2018/09/02

しかし、これだとExcelに張り付けたときに見栄えが悪いので、”年月日{タブ}件数”の様に出力順を入れ替えた。

>

1
> res.txt

これまでの処理結果をres.txtに保存した。

まとめ

ここまでくれば、この結果をテキストエディタで開きコピー、Excelの空のシートに張り付け、貼り付け結果のデータをテーブルに変換し、ピボットグラフを作れば集計は終わりだ。

簡単だし、結構なスピードで集計が完了した。
たまにはコマンドも良い。

同じタグの記事
同じカテゴリの記事

Pythonで文字列が含まれているかどうかを調べる

Pythonで文字列が含まれているかどうかを調べる

あいかわらず、ログファイルを集計している。
ログファイルに特定の文字が現れる行の行数を数えたい。

文字が含まれているかどうか

strのfindを使うと、他の言語のindexOfの様に位置を出現個所の位置を返してくれるようだ。

1
2
3
line = 'test message'
print(line.find('mes'))
print(line.find('mec'))

上記の例だと、最初が5、次が-1が返る。
-1より大きいかどうかを判断すれば文字が含まれるかどうかをチェックできる。
しかし、今回は位置は必要ない。
そういう場合は、配列に含まれているかどうかと同様に in を使えばよい。

1
2
3
line = 'test message'
print('mes' in line)
print('mec' in line)

上記の例だと、最初がTrue、次がFalseが返る。
スマート。
そして、統一感がある。

まとめ

inで含まれているかどうかが、配列でもディクショナリでも文字列でも扱えるところは統一感があって素晴らしい。
ちなみに、Kotlinであればcontainsがそれにあたるのだろう。

同じタグの記事
同じカテゴリの記事

Pythonでディレクトリ走査

Pythonでディレクトリ走査

相変わらず、ログファイルを集計している。
特定のディレクトリのファイルをすべて検査するのだが、今まではosモジュールを利用していた。

os.listdir

1
2
3
4
5
6
7
import os

top_dir = '/logs'
for f in os.listdir(top_dir):
    path = os.path.join(top_dir, f)
    if os.path.isfile(path):
        print(path)

今までは、この方法を実行していた。
しかしこの方法は、os.listdirの戻り値がファイル名のみなので、そのファイルにアクセスしようと思うと、top_dirとos.path.join()しなくてはならない。
Python3.4からはpathlib.Pathが利用できる。

pathlib.Path

1
2
3
4
5
6
from pathlib import Path

top_dir = '/logs'
for f in Path(top_dir).iterdir():
    if f.is_file():
        print(f)

iterdirの戻り値はPathなので、そのメソッドを利用しファイルかどうかを確認し、Pathなので__str__でフルパスを取得できるし、nameではファイル名のみの取得もできる。suffixで拡張子のみの取得もできる。とても便利。

まとめ

これからはPathを率先して利用しよう。

同じタグの記事
同じカテゴリの記事

Oracleに負荷をかけているプログラムを探す

Oracleに負荷をかけているプログラムを探す

OracleサーバのCPUの1つのコアが100%利用されている。
LinuxのtopコマンドでoracleORCL(LOCAL=NO)が利用しているのはわかったが、どこからのアクセスでそうなっているのかわからない。
LinuxのプロセスIDからアクセス元を特定できないものか。

V$PROCESS

V$PROCESS.SPIDがプロセスIDのようだ。

1
2
3
4
5
6
SELECT
    *
FROM
    V$PROCESS
WHERE
    SPID IN (15254)

SPIDに指定しているのはtopでCPUを100%使用していたプロセスのプロセスID。
しかし、V$PROCESSだけでは、プログラム名や接続元が取得できない。
V$SESSIONを結合する。

V$SESSION

1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT
    S.PROGRAM,
    S.USERNAME, -- ORACLE接続ユーザ
    S.OSUSER, -- OSユーザ
    S.MACHINE, -- 接続元ホスト名
    S.PROCESS, -- 接続元ホストでのプロセスID(取得できれば)
    S.EVENT
FROM
    V$PROCESS P
    JOIN V$SESSION S
    ON P.ADDR = S.PADDR
WHERE
    P.SPID = 19391;

これで、接続元の情報が取得できた。
なお、動的ディクショナリビュー同士の結合は推奨されないようだ。

MACHINE列に表示されたサーバに接続し、そのサーバでプロセスプロセスIDを検索する。これで犯人がわかった。
ちなみに、プロセスIDの取得ができない場合は1234が設定されるようだ。

接続元情報を得る

この際、負荷の高いプロセスの接続元だけではなく、すべて表示してみる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SELECT
    S.PROGRAM,
    S.USERNAME,
    S.OSUSER,
    S.MACHINE,
    S.PROCESS,
    S.EVENT,
    P.PROGRAM,
    P.SPID
FROM
    V$PROCESS P
    JOIN V$SESSION S
    ON P.ADDR = S.PADDR
ORDER BY
    S.PROGRAM,
    S.MACHINE,
    S.PROCESS;

意外と接続されていることが分かった。

まとめ

運用始めてから5年以上経つOracleが、思いもよらないサーバからアクセスされていることに気が付いてしまった。今回の高負荷の原因とは関係ないアクセスだったが、一応ブロックしておこうか。

同じタグの記事
同じカテゴリの記事

Pythonで日付、時刻の比較

Pythonで日付、時刻の比較を行う

急に性能が落ちてきた処理がある。しかし、それがいつからなのか、体感的なもので本当はたいして性能劣化していないのか。
よくわからなかったので、ログファイルを集計して処理時間を計測してみることにした。

簡単に作りたかったのでPythonを利用する。
文字列の日時をdatetimeに変換して、datetimeとdatetimeを引き算し、返ってきたtimedeltaから差を得ればよいようだ。

文字列からdatetimeへの変換

1
2
3
4
import datetime

start_date_time = datetime.datetime.strptime('2018-09-14:14:49:31', '%Y-%m-%d:%H:%M:%S')
end_date_time = datetime.datetime.strptime('2018-09-14:14:51:13', '%Y-%m-%d:%H:%M:%S')

日付のフォーマットを指定すれば、ログファイルの日付フォーマットはいろいろ対応できそうだ。

処理時間を算出する

1
2
3
dist_delta = end_date_time - start_date_time
print(dist_delta.seconds)
print(dist_delta.days)

secondsで差の秒数を取得できる。
何日も差があるようであれば、daysで差の日付を取得できる。

まとめ

数十万行のログファイルから特定のキーで開始時間と終了時間を取得しつつ、処理時間の平均を日ごとに集計したが、1分未満で処理が終わった。Python優秀だ。

同じタグの記事
同じカテゴリの記事

PythonでCSVファイルを読む

PythonでCSVファイルを読む

テキストデータを読むバッチを度々作る。
昔からの習慣でカラムの区切りはタブかバックタブを利用し、プログラムでsplitして読んでいた。特にPythonは簡単に使えるので、.strip()してから.split(‘\t’)という習慣があった。
しかし、CSVファイルを出力するプログラムが、先方の仕様で出力されてしまう場合、それに合わせて読み込む必要がある。
区切り文字だったり、各カラムの囲み文字があったり、自前のプログラム対応するのは面倒だ。そんな時csvモジュールを使う。

CSVファイルを読む

1
2
3
4
5
6
import csv

with open('sample.csv', 'r') as r:
    reader = csv.reader(r, delimiter=',', quotechar='"', skipinitialspace=True)
    for row in reader:
        print(row)

delimiterは区切り文字。デフォルトは’,’。
quotecharはカラムの囲み文字。デフォルトは'”‘。
skipinitialspace=Trueは、区切り文字の前後のスペースを無視してくれる。CSVファイルではあまりないだろうが、下記のようなデータの場合に、都合よく処理してくれる。

1
"ABC", "DEF", 30

skipinitialspace=Trueが指定されないと、2カラム目は’ “DEF”‘になってしまう。
扱うデータによってはスペースにも意味があるかもしれないので、理解して利用する。

まとめ

Python2の頃は、strとunicodeの違いで、日本語が含まれるファイルを読むのに苦労したが、Python3なら何も気にせず読み込むことができる。
これからはcsvモジュールを利用するようにしてみよう。

同じタグの記事
同じカテゴリの記事