それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

pyenvを使って、pythonをインストールしてpython環境を使う。

pyenv をインストールする。

python 3.6 を使いたいなと思ってインストールをはじめました。

ユーザー空間にvirtualenv 作るより楽ちんだし pyenv 使おうぜ

インストール

git clone git://github.com/yyuu/pyenv.git ~/.pyenv

macOS なひとは

brew install pyenv

pyenv を起動するためのbashrc設定

pyenv は rbenvと同じくbash の機能を使ったPATH変更的に動くので、シェルの環境設定は大事

# pyenv を使う
if ( type  pyenv > /dev/null 2>&1  ||  [[ -d  ~/.pyenv  ]] ) &&  [[ $TERM != screen* ]] ; then
  ### pyenv
  export PYENV_ROOT="$HOME/.pyenv"
  export PATH="$PYENV_ROOT/bin:$PATH"
  eval "$(pyenv init -)"
fi

あとはコレを読み込めば準備完了

pyenv を使ったインストール

pyenv install 3.6.1

常時に使用するように設定

pyenv global 3.6.1

または特定のディレクトリで起動するようにセッティング

pyenv local 3.6.1

もともとあるpythonに戻そう

一時的に OS側に用意してある python に戻したいときは

python global system

これでオッケー。

pip もバージョンごとで管理される

pip で入れたパッケージも バージョン毎に管理される。

takuya@:~$ pyenv global 3.6.1
takuya@:~$ python -V
Python 3.6.1
takuya@:~$ pyenv global system
takuya@:~$ python -V
Python 2.7.9
takuya@:~$ mycli
pyenv: mycli: command not found

The `mycli' command exists in these Python versions:
  3.6.1

これは相当に楽ちんですね。

twitterの検索方法:自分の過去のツイート検索したり、リツイート検索したり、便利な検索方法

あのツイートどこだっけ?

あーあの retweet したやつ何処だっけ
あのときにTweetしたやつなんだけど

などと過去のリツイートやツイートを検索したいことが多々有りますよね。

検索方法が有ります。

引用元

たとえば自分の過去のツイートをRT含めて掘り出したいとき

ダイエット  include:nativeretweets from:自分のユーザーID

from:user_id@user_id でも代用できる

例ユーザーの過去のツイートから検索するには

ダイエット from:自分のユーザーID

例 ユーザーのツイートを日付(期間)で絞り込む

ダイエット until:2017-05-25 from:ユーザーID

@userID でメンションされてるのを探すには

ダイエット @userID until:2017-05-25 from:発言者

たとえば、オッパイ画像をさがすなら

リツイートがおおい画像を含むツイートを検索する例

filter:images min_retweets:1000 おっぱい

などとすることで、トレンドの検索ができる。でもトレンド検索はあまりあてにならないかも・・・

危険な発言と判定されているものを知る。 2023-05-20

from:takuya_1st -filter:safe

ツイッターが投稿内容を「危険」かどうか判定してセーフティか判定している。自分の投稿で「不適切」と判定されているものを調べることができる。

favorites もほしいなぁ

自分がふぁぼった(like/いいね)した一覧を見るのはAPI経由になるかも。。。

どうでしたか?

ツイート検索をして、彼氏の元カノや彼女の元カノを探したり、彼氏の裏垢をさがしたり、ツイート検索を覚えるだけで意中のターゲットのツイートを地域名や時間などで検索して掘り起こすことが出来ます。またあの頃言われたあの言葉のツイートを掘り起こしてニヤニヤすることも出来ます。

ちなみに、OR検索もできるらしいよ。

[asin:B00C1QD1W0:detail]

2023-05-20

不適切発言判定、safe について追記。

参考資料

tailコマンドで複数のログをまとめて表示する

同時に2つのログを見たい

tail -f を2つ起動して、ターミナル並べておくのも邪魔くさいと思ってました。

tail -f /path/to/log2 /path/to/log1 

こうすれば、複数のログファイルを同時に tail でウオッチできる。

いままでは

watch と cat を組合せてたのでこれは目からウロコだった。

実際に実行した例。

takuya@Desktop$ tail -F a.log b.log
==> a.log <==
aaaaa

==> a.log <==
aaaa

==> b.log <==
bbbb

==> a.log <==
aaaa

ログが書かれるたびに交互に表示されるので便利だった。

参考資料

https://hydrocul.github.io/wiki/commands/tail.html

tail コマンドがファイルの削除、作成時でも動くようにする

tail -f コマンドを使うとファイルの削除で動作が止まる。

tail -f /path/to/log

で ログファイルを見ているときに、別のプロセスでファイルが消えたら

ファイルが消えたら、動作が止まる。

mv /path/to/log /dev/null
rm /path/to/log 
echo hello > /path/to/log 

これはファイルディスクリプタだけを見ているので、ファイルが消えるとログを追尾できない

-F / –follow=name を使う

tail -F /path/to/log
tail --follow=name a.log

これでパス名のファイルの有無などを監視してくれるようになる。

tail -f は inotify や fsevent を見てると思うので、基本的には -F で良い気がする。

man tail

-f, --follow[={name|descriptor}]
              output appended data as the file grows;

              an absent option argument means 'descriptor'

-F     same as --follow=name --retry

inotify を見てる話はman にそう書いてる。

      -s, --sleep-interval=N
              with -f, sleep for approximately N seconds (default 1.0) between iterations; with inotify  and
              --pid=P, check process P at least once every N seconds

tail -f コマンドがログ監視てるプログラムが死んだら一緒に自動的に終了する

pid を指定すると tail コマンドが自動的に終了する

tail -f --pid=$PID /path/to/log

PIDを指定したときに

ローカルホスト開発ツールのログ監視してるときとかに便利ですね。

man tail

       --pid=PID
              with -f, terminate after process ID, PID dies

参考資料

https://hydrocul.github.io/wiki/commands/tail.html

ChromeのDeveloper tools(開発ツール)のコンソール(コマンドライン)で出てくる記号と関数

chrome の dev tools に出てくる関数

$ と $$ の違い

$ = document.querySelector
$$ = document.querySelectorAll

$x は Xpath

$x('//a')

xpath は組み立てと呼び出しが面倒なので、とても嬉しい。

その他の関数をマトメておくと

クエリ系

  • $
  • $$
  • $x

直前のものを再利用

  • $_

選択された要素

  • $0
  • $1
  • $2
  • $3
  • $4

デバッグ

  • debug
  • monitor/unmonitor
  • table
  • copy
  • profile/profileEnd

要素やオブジェクトの検証

  • inspect

イベントハンドラの監視と調査

  • getEventListeners
  • monitorEvents/unmonitorEvents

参考資料

https://developers.google.com/web/tools/chrome-devtools/console/command-line-reference?hl=ja#04

右クリックでEvernoteに送信する

右クリックでEvernoteにファイルを送りたい

Finderで右クリックでファイルをEvernoteに送るにはどうするか。

「このアプリケーションで開く」→「Evernote」とすればいいし、項目にEvernoteがなければ、その他から選べばいいいのですが。。。

最初から用意されてない拡張子が出てくるたびに登録するのが面倒くさい。UTI書き換えれば良いんだけどそれも面倒に感じた

右クリックメニューのサービス項目を作成した

f:id:takuya_1st:20170510154650p:plain

サービスを作ってすべてのファイルを大正にした。

前に作った コマンドを呼び出すようにする。

#!/bin/bash

path/to/file2evernote.js "$@"

右クリックメニューで出てくる

f:id:takuya_1st:20170510154828p:plain

これで気にせず使える。

ぱぱっとEvernoteにPDFやJPEGmarkdownCSSを放り込んで楽をすることが出来た。

Evernoteにファイルを投入するコマンド

Evernoteにファイルをまとめて放り込みたい。

コマンドでまとめてEvernoteに放り込みたい。APIを経由すると毎年〜キーを更新しなくちゃいけないので面倒くさい

なので、Apple Script ( の JavaScript ) でやろうと思う ( Windows な人は同じ目的で enscript.exe が使えます)

JavaScriptで自動化するときのポイント

コマンドを使って起動するときは

#!/usr/bin/env osascript -l JavaScript

ObjC.import('stdlib')  
/// ここがmain関数に相当する
function run( argv ){
  console.log("Hello World")
}

Evernote に新規ノートを作ってファイルを貼り付け

Evernoteに新規ノートを作ってファイルを貼り付ける場合は、次のようにする。

  var name = 'no title'
  var file_path = '/Users/takuya./.bashrc'
  var app = Application("Evernote")
  var notebooks = app.notebooks
  var defautNoteBook = Array.apply(null, notebooks).find(function(e){ return e.default })
  var note = app. createNote({
    title: name,
    notebook: defautNoteBook,
    withText : name
  })
  note.append({ attachment: Path(file_path) })
  app.activate()

NSString とFileManagerを使ってPATHの存在チェックなど

realpath と file_exist? をやって引数チェックする

file2evernote.js

ObjC.import('Cocoa')
nsStr = $.NSString.alloc.initWithUTF8String(file_path);
file_path = nsStr.stringByStandardizingPath.UTF8String;
mgr.fileExistsAtPath(e)

これをまとめてコマンドにする

引数で受け取ったファイルを一覧を処理してEvernoteに貼り付ける。

gist.github.com

使い方

./file2evernote.js *.jpg

JXAのJavaScript AutomationとObjc Cocoaのオブジェクト呼び出し例

JXA で NSString を使ってPATHの変換をしてみたのでメモ

objcのCocoa から NSString と FileManager を使ったので、いろいろ知見を得られたのでメモ。

Javascriptで、NSString を使うには、次のようにする。

ObjC.import('Cocoa')

NSStringを init して alloc する

## [[NSString alloc] init]
$.NSString.alloc.init

JS の文字列から NSString に変換する。

// [[NSString alloc] initWithUTF8String:"Hello world"];
nsStr = $.NSString.alloc.initWithUTF8String("Hello World.");

NSString から JS の文字列に変換する

JS文字列は基本的にObjC→C言語へ変換するのと同じ

// [@"Hello world" UTF8String]
var str = nsStr.UTF8String;

メソッドを呼び出す。

nsStr = $.alloc.initWithUTF8String("/Users/takuya/.bashrc")
nsStr = nsStr.stringByStandardizingPath
nsStr = nsStr.stringByStandardizingPath.UTF8String;

メソッドの呼び出しは CoCoa を書いてるときみたいに書けばいい。むしろ最後の丸括弧を除去した方がいいところが面喰らう的な。getter/setter なんかも同じ。

ポインタを引数に取るメソッドを使うとき、キーワード引数を使うとき

// - (BOOL)fileExistsAtPath:(NSString *)path isDirectory:(BOOL *)isDirectory;

mgr = $.NSFileManager.defaultManager;
var isDir= Ref();
mgr.fileExistsAtPathIsDirectory(e,isDir) && isDir[0]

変数のポインタを扱うのは var ptr = Ref() で、デリファレンスするのは ptr[0] のように配列の中身を見る感じっぽい 同じ関数 fileExistsAtPath でもキーワード引数をつけるなら、引数を関数名にするのがみそらしい

参考資料

すごくわかり易い例がいっぱいあって助かりました。

http://palepoli.skr.jp/tips/javascript/jxa.php

Selenium で フォーム送信

Selenium で フォーム送信 するには。

若干のWaitを入れてあげるとうまく動くと思う。

driver.goto 'https://example.com/login'
wait = Selenium::WebDriver::Wait.new(:timeout => 3) # second
## ページロードを待つ
wait.until { driver.xpath('//*[@id="clogs"]/input[1]').displayed? }
## フォーム送信をするには send_keysを使う
driver.xpath('//*[@id="clogs"]/input[1]').send_keys('takuya***')
driver.xpath('//*[@id="clogs"]/input[2]').send_keys('***')
driver.xpath('//*[@id="clogs"]').submit

Selenium使おうとしたらchromedriverが古くてエラーになった。

selenium 使おうとしたらエラーになった。

>> require 'selenium-webdriver'
=> true
>> driver = Selenium::WebDriver.for :chrome , :desired_capabilities => caps
NameError: undefined local variable or method `caps' for main:Object
from (pry):2:in `__pry__'
>> driver = Selenium::WebDriver.for :chrome
EOFError: end of file reached
from
>>

EOFErrorになったので調べたら、 ChromeDriverが古い事が原因のようです。

バージョン確認

takuya@Desktop$ /Users/takuya/repos/my_command/usr/local/bin/chromedriver -v

バージョン確認したら 結構古かった。はずかしいのでバージョンは書かない。

brew でアップデート

brew でパッケージが提供されるようになったので楽ちん

takuya@Desktop$ brew install chromedriver
Updating Homebrew...
==> Auto-updated Homebrew!

アップデート後に再確認

>> require 'selenium-webdriver'
=> true
>> driver = Selenium::WebDriver.for :chrome
=> #<Selenium::WebDriver::Driver:0x..fa2af2f73e150f72c browser=:chrome>
>> driver
driver
>> driver
driver
>> driver.close
=> nil
>>

問題なく動く。EOF Error が バージョンだと気づくまでに1時間位かかった。迂闊だった。

tailf と grep を組合せて Slackにログを通知する。パイプでワンライナー

ログファイルを監視して、slack などに通知したい。

ログを監視して Slackに投げる方法で、かんたんなのを考えた。

ログファイルに何か変更があって、それが特定のときに メールや slack のチャンネルに通知を出したら便利だと思う。

あれこれログ監視や通知のソフトウェアやパッケージがあるけれど、一番大事なのは手軽で何も知らなくても使えることだと思う。

ファイルを監視して grep して HTTP POST するだけなら、パイプで十分に使える。

ログ監視の仕組み

要は、次のコマンドパイプを呼び出せればいい。ただしいくつかポイントが有るので、それを見ておく

目指す形

このエントリでは次のようなコマンドを作る

tail -f path/to/file | grep some_thing |  curl -X POST url

このままでは動かない。

コマンドの組合せならすぐ思いつきそうなパイプですが、単純にこのコマンドだけでは動きません。tai や grepcurl コマンドの特性上、このままではパイプで動かない。すこし変更が必要でした。

コマンドの問題点

tailf / tail -f ではログがローテーションしたときにOpenしたファイルを追尾しない。新しいログファイルを開いてくれない。そのため、このままでは動きませんでした。

grepは、そのままでは次のパイプがリアルタイムに起動しませんでした。

curl コマンドは、この書き方すると標準入力行を全部受け取ってしまいます。

これらを防ぐために若干のコツというか、オプションを調べて見直したので、まとめておきます。

tail -F でパスを監視する

tail コマンドには -F というオプションがあり、これで該当PATHのファイル監視を出来る。 もし tail -fで監視していると、ファイルが削除・移動後に追跡できない。そのため、tail を使った長期間ログ監視なら、次のコマンドが望ましい。

ログ監視の一番かんたんなコマンド

tail -F logs/lastest.log

追加された行だけを取得する

tail を起動すると、最終5行を表示して -f : follow モードに入る。そのため起動すると過去ログが何度も通知されるのが望ましくない。

tail -n0 -F logs/lastest.log

tail と grep の組合せ

tail -n0 -F logs/lastest.log | grep takuya

tail -f とコマンドの組合せが便利。

パイプ先で必要情報だけを取出して、残りを捨てたフィルリングや書き換えが出来る。

tail と grep を組合せれば、ログをフィルタできる。また-f / -Fをつけたtail は、パイプがブロックIOになるので、ログが更新にリアルタイムで追従してくれる。

tail | grepにさらにパイプをつなぐ

### リアルタイム動作しない
tail -n0 -F logs/lastest.log | grep  takuya  | grep login

tail | grep は正しくフィルタするが、 tail | grep | grep は画面出力が得られない。 なぜか?。

grep tail -f の組合せは、grep パイプ後パイプが動かない時がある。これはgrep がバッファリングしてしまう事が原因です。

実は grep が内部的にバッファリングして、高速化してくれる。そのため tail -f | grep | grepでは、中間のgrepがIOをバッファリングして、最後のgrepに即時にログが届かない。

line-buffered のオプション

次のオプションで、複数行バッファリングを一時停止(行単位で出力バッファ)するようにする。

man grep
      --line-buffered
              Use line buffering on output.  This can cause a performance penalty.

tail | grep | grep するときは次のようにする。

そのため tailf を grep して grep したり、sed したりする場合は、 次のようにする。

tail -F logs/lastest.log | grep --line-buffered takuya  | grep --line-buffered  login

ログを受け取ったら、何かする。

行単位でログがやってくる。

行単位で受け取ったらPOST処理をするとしたら、curl でPOSTしようとすると、行を標準入出力から受け取る必要がある.

出来ない

grep something | curl -X POST -d - ... 

grep した結果をcurl で送信しようとしても、curl で標準入出力をパイプで扱うと、1度しか起動できない。行毎に起動するには xargs を使う

xargs で行が来るたびに送信する。

 grep --line-buffered takuya  | xargs -I@ curl -X POST http://example.com/ -d message="@"

xargs を -I で1行単位で起動するようにして、@` という文字で指定して、1行をコマンドの文字列に展開する。

slack のURLを用意する

Slack にはPOST用の webhook が用意されていて、最近はチャンネル毎にPOST用のWebhook のURLを生成できる 生成したURLは次のように、ディレクトリが3段になっていた (2017/05/09)

https://hooks.slack.com/services/Axxx/Bxxx/Cxxx

ここに curl で post / json すれば、 Slack に拾われる。

curl -s  \
  https://hooks.slack.com/services/Axxx/Bxxx/Cxxx \
   -X POST \ 
   -H 'Content-type: application/json' \
    --data '{"username":"curl", "text":"#{my message}"}'

パイプにまとめる。

ここまで見てきたそれぞれのコマンドとパイプを全部まとめると、次のようになる。

tail -n0 -F logs/lastest.log | grep --line-buffered takuya  |  xargs -I @ curl -s  \
  https://hooks.slack.com/services/Axxx/Bxxx/Cxxx \
   -X POST \ 
   -H 'Content-type: application/json' \
    --data '{"username":"curl", "text":"@"}'

これで、ログが更新されたら、 grep で フィルタをかけ、条件にあったログが来たら Slack にPOSTすることが出来る。

さらにコレを関数か、シェルスクリプトファイルにする

このままでは、ファイルの指定とエンドポイントのPOSTのURLが変更が不便なのでシェルスクリプトにしておくと便利だと思います。

さらに、systemd に登録

これらのコマンド(シェルスクリプト)をsystemd.unitの service に登録して、Daemonと同時に起動しておけば、だいぶ楽だよね。

マインクラフトのログを監視する

たとえば、マインクラフトサーバーで「死んだ」人をSlackに晒し上げるには

ログファイルが lastest.log で、grep で slain を取れば死んだことが解り、最後にSlackで通知したら出来上がり。

tail -n0 -F logs/lastest.log | \
grep --line-buffered slain  | \
xargs -I @ curl -s  \
  https://hooks.slack.com/services/Axxx/Bxxx/Cxxx \
   -X POST \ 
   -H 'Content-type: application/json' \
    --data '{"username":"minecraft-serverl", "text":"@"}'

コマンドで出来てるので、たとえば、死んだ回数や死因を累計とか、ログイン・ログアウトを監視してプレイ時間を通知するとかね。

まとめ

tail と grepcurl だけで、ログを監視して通知することが出来ます。

tail -F で ファイルのパスの状態を監視できます

grep –line-buffered で行ごとにgrep をすることが出来ます。

xargs curl で行の内容をPOSTすることが出来ます。

個人的な

ちょっとしたログ監視を調べたら、ちょっとね・・・

「最強の○○のログ監視」と「ログ監視パッケージをdocker コンテナ」を導入してる 某キ◯タさんの意識高すぎるエントリに辟易して調べました。

開発とかちょっとしたことにわざわざDockerコンテナだのAWSとか、ちょっと重たすぎだよね。手順やリソースが多すぎる。

ログ監視ってのは単一のログファイルを見て何かするのと、「複数サーバー(インスタンス)」のログを一箇所に集めて何かするのとだいぶ違うと思うんだよね。

Slackに投稿したり、ログを投げたり、まとめたりっていろいろな方法がある。パッケージを入れてしまえばたしかにかんたんなのですが。後始末が面倒になる。後始末が面倒になってたくさんのインスタンスを使い潰したりコンテナから起動したりで、時間や学習コストは抑えられるのですが。金銭的に不利だったり、学習コストを抑えたために、応用が効かなかったり。。。うーんって思うことも有る。

google chrome が google アカウントのパスワードを補完(入力しない問題

Google Chrome がパスワードを利用させてくれない

ChromeGoogleアカウントでログインしてる場合、そのアカウントのパスワードは補完されない。

そのために、Chromeでパスワードを何度も入力することになり面倒くさい。

原因と理由

ちょっと実験してみた。

Chromeブラウザにログインしてるアカウントのパスワードを「バックアップ同期」している場合に起きる。つまり、Chromeブラウザからログアウトするとパスワード補完は復活する。

なぜこの仕様、これが鬱陶しく面倒になるのか?ここ最近のGoogleアカウントはパスワードの再確認が頻繁に起きるようになった。いぜんは手軽にアカウントを切り替えなどが出来たのに。最近はアカウントを切り替えることも面倒くさい。

解決策1

Chromeをログインせずに使う。Chromeにログインせずに利用すれば、いかなるGoogle アカウントでもパスワード自動入力が動く。

解決策2

Chrome にログインしてる場合、パスワードの同期を外す。

これはChromeにログインして、拡張機能やブックマークやセッションなどをバックアップ同期したい場合に有効

[f:id:takuya_1st:20170507184544p:plain:300]

解決策3

Chromeにログインし同期する専用のアカウントを作る。

GmailやOAuthのログイン連携で常用するアカウントと、Chromeにログインしてバックアップを取るアカウントを分けてしまう。

参考資料

https://productforums.google.com/forum/#!msg/chrome/xjXc0i-bqNs/-js6NHZACAAJ

素因数分解をしてくれるコマンド factor

prime numbers ( 素数 ) に分解してくれるコマンドがあった。

takuya@Desktop$ factor 123456
123456: 2 2 2 2 2 2 3 643

factor とは 要因の意味で数学的に因数で、factor コマンドは 素数を使って因数を表現してくれるコマンド

何に使うのか。

特に何に使うわけでもないけれど、コマンド呼び出しやexec 系やパイプの実験のサンプルに丁度いいと思います。

takuya@Desktop$ irb
>> exec 'factor 10'
10: 2 5

標準入出力を使った例

コマンドはブロッキングIOで逐次処理されるので、IOを使った実験に向いている。

takuya@Desktop$ factor
43
43: 43
22
22: 2 11
11
11: 11
1111
1111: 11 101

このようにコマンドの実行サンプルの例として使うのに向いてるのかもしれない。

何処に入ってるのか?

coreutils に入っています。

mac なら 次のようにするとインストール出来ます。

brew install coreutils

シェルスクリプトの改行コードを修正する

改行コードが原因でエラーになる。

改行コードを \r\n が原因でエラーになった。

takuya@:~$ bash -n apt
apt: 行 2: 予期しないトークン `$'\r'' 周辺に構文エラーがあります
'pt: 行 2: `_apt()

一瞬何のエラーかわからなかったけどよく見るとエラーに改行文字が含まれてた。

改行コードを修正するコマンド dos2unix

インストール

sudo apt install dos2unix

実行

dos2unix an.sh

とても便利ですね

似たような仲間には

  • /usr/bin/dos2unix
  • /usr/bin/unix2dos
  • /usr/bin/unix2mac
  • /usr/bin/mac2unix

などがあります。CRLF : dos/windows 、 LF : UNIX / bsd / linux , OS X(macOS) , CR : Mac OS(9) などですね。

過去資料

改行コードを置換する専用コマンド - それマグで!