それマグで!

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

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

macのスマート引用符・スマートダッシュ機能が罠だった。

なんかオカシイなと思ったら

スマートダッシュ・スマート引用符で自動変換されていた件。

Evernote に適当にコードメモしたのが動かなくて

Evernoteに適当にメモしたコード断片をIPython や Pryに貼り付けたら動かなくて、なんだこれ? とおもってよく調べてみたら、引用符が引用符じゃなくなっていた。

引用符が引用符じゃなくなっていた。

お前は何を言ってるんだ?

f:id:takuya_1st:20170626154649j:plain:w150

私も一瞬パニックになったのですが。

よく調べてみたら、ダブルクォートじゃなくて、別の引用符に変換されていました。

いつ起きたのかと調べてみたら、どうやらスマート引用符という機能のようです。

f:id:takuya_1st:20170626153935p:plain

f:id:takuya_1st:20170626153947p:plain

スマート引用符の例

スマート引用符が有効になった状態で、ダブルクォートを入れると、自動的に「引用符」をキレイにしてくれる例です。

www.youtube.com

スマートダッシュの例

同じように、スマートダッシュについても見てみました。ハイフンが変換されていました。

www.youtube.com

防ぐ方法

自動変換機能をオフにするのが一番です。

小さめのフォント(10px前後)を使っていると見逃すので注意が必要です。

クラス・メソッドをインスタンス内から呼び出す

ruby でクラスに所属するメソッドを呼び出す。

クラスに所属するStaticなメソッドを呼び出したときに、クラス名を直接指定するのは不便だよね。

class A
   def  self.do 
       puts :do
   end
   def say
       A.do # クラス名が・・・
   end
end
a = A.new
a.say

self で参照する

self.class で参照すると楽ですね。

self.class.do

ついでに send も取り入れるともっと楽かも?

Object.send でメソッド名を sym か str で指定できるので、そっちを使っても便利かもしれない。

class A
   def  self.do 
       puts :do
   end
   def say
       self.class.send(:do)
   end
end
a = A.new
a.say

これで、むやみにインスタンスメソッドを生やさなくて済む。インスタンスメソッドは「インスタンス」を扱うようにしたいよねやっぱり。インスタンスが無くても動くような処理はクラス・メソッドに登録しておくと使い方を変えられるので意図が明確になる気がする。

クラスの特異メソッドにモジュールのメソッドを取り込む

モジュールのメソッドを、クラスの特異メソッドに取り込む

module で定義した、メソッドやローカル変数を、クラスの特異メソッドに取り込む

次のようにすると実現できる。

module S1
  def sample
    puts :sample
  end
end

class A
  class << self
    include S1
  end
end

共通処理をクラスに書いてしまうとクラスのStaticな部分とインスタンスな部分がごちゃ混ぜになってしまうので、分けて書けるのはMix-inが強いなと思いました まる。

ただ、include や モジュールでほしいのは関数定義 def だけだったりするので、名前空間が独特でruby 分かりづらいよねともおもったり。クラスの継承をしなくて良いのは楽よね。

自動的にmysql のバックアップを取ってくれる automysqlbackup

ぼーっとしててやらかした。

履歴から入力してて、イライラしてるときに、truncate コマンドを本番環境に実行してしまった。もう詰んだ。死にたい。

二度とこんなことがないように

automysqlbackup

というパッケージを導入することにしました、

apt で

apt install automysqlbackup

mysql と一緒に入れておきましょう。

以前入れていたと思ったら、入って無くて本当に詰んだ。

Twitter の OAuth でメールアドレス求めるのはやめてほしい

なぜTwitterで新規登録すると「メールアドレス」が求められてしまうのか。

Twitterの認証連携をして、AuthorizeApp したあとにメールアドレスの確認が必要になる。ほとんどの「JPサービス」はこの形態を取る。

f:id:takuya_1st:20170723160732p:plain

OAuth わかってんのか

認証を丸投げしてるんだからメールアドレスを必須にされても手間が増えて困るだけなんですよ。

かといってFacebookで認証連携なんてフレンドリストやメールアドレスを抜かれて困る。

メールアドレスをわたしたくないのでTwitterを選ぶ

選ぶんだけどメアドが必須にされるのはナゼ?

わたしには理解できないです。そのそも設計がオカシイんじゃないのか。

それとも法律で「メールアドレス」を回収するように求められるのかな?公衆無線LANのように??

作成済みのm5sumとぱぱっと比較する方法(改竄検出の楽な方法

md5sum の -c オプション

-c 生成済みの md5sum の一覧とファイルを比較して改ざんを検出する。

事前にファイルのmd5sum の値の一覧を作成しておき、いまのファイルがそのファイルのハッシュ値と一致するかを調べておく。すると簡単に改竄検出や不正検出を見つけることが出来る。

使い方

最初に、md5sum の一覧を計算してファイルに書き出しておきます。

md5sum sample.txt > out.md5

次に、この出力結果を使ってファイルが一致するかチェックします

md5sum -c out.md5

out.md5の中身は次のようになっています。 md5値 ファイルPATHが列挙されています。

c3cec535915d86f2ce51c668f6919696  sample.ext

チェック-cの場合は、右側のファイルパスのファイルを探して、md5値を導出し事前に計算していた左側に一致するかを調べてくれます。

指定したフォルダの中をマトメてチェック

1ファイルだと何の役に立つかわかりにくいのですが、フォルダの中のまとめてチェックすると強いです。

find コマンドや xargs と組合せる。 フォルダのすべてのファイルについて、md5を計算する

sudo find /etc/  -mindepth 1 -type f   -exec md5sum {} \; > etc.md5

結果を使って、フォルダの中のすべてのファイルについて、ファイルの改竄検出を行う。

sudo md5sum -c etc.md5

if 文で使う

bash の if 文でつかときは --status オプションが便利です。

このオプションを付けると、表示をしない代わりに、チェック結果をコマンドの実行結果で返してくれます。

if ( md5sum -c --status etc.md5 ) ; do 
  echo "改竄チェックOK"
else
  echo "改竄チェックNG"
fi 

これで有るフォルダの中が書き換わってないかを手軽に調べることが出来ます。

もしチェックに失敗したファイルを見つけたいときは

sudo md5sum -c   out.md5 | grep -i failed

のようにしたら見つけることが出来ました。

もっと簡単にするには、

sudo md5sum --quiet -c   out.md5 

--quiet don't print OK for each successfully verified file このオプションをつけるのもいいでしょうね。

ハッシュ値をまとめて保存とは

もし、ハッシュ値保存したファイルを改ざんされると怖いので、ハッシュ値を保存したファイルのハッシュ値を取ってそれをブロックごととに保存していくといいです。このブロックが・・・

ブロックチェーン技術などで盛んにファイルの記録をハッシュ値で云々と叫ばれてます。 基本的にはハッシュ値を計算してファイルに保存してそのファイルのハッシュ値を計算してーってことです。似たようなものです。

フォルダの中のファイルつまり、あるエントリの内部のハッシュ値をすべて見るには、md5sum である程度十分です。便利だし。

衝突の可能性も有るでしょうがローカルファイルで衝突は可能性が低いしね。

参考資料

How to access all your cloud files in one place in Windows 10 | TechRadar

みんな大好き! man

nkfの使い方:base64のエンコードとデコード(ただし文字列だけ

nkf だけで base64エンコードとデコードが出来る

nkf には -mB-MB のペアがあるのでBase64エンコードとデコードが出来る。

nkfbase64 エンコード

echo  -n こんにちは | nkf -MB

nkfbase64 デコード

echo 44GT44KT44Gr44Gh44Gv| nkf -mBW
こんにちは

入力の文字コードを -W : utf8 で指定してる。

主に文字列

文字列だとうまくいく。nkf は「文字コード」を変えるコマンドなので、バイナリも文字として扱ってしまうのでデータは壊れる。アレコレすればいいだろうけど、そこまでやる必要は特になくbase64 コマンドを使ったほうが良いので。

関連記事

nkfでURLエンコードされた文字を扱える(エンコード・デコード・文字コード)

nkf だけで、URIエンコードされた文字を扱える

とある文字列を処理していて、CP932(Shift_JIS ) がそのまま、URLエンコードされた文字に出会って、ちょっと面倒な自体になった 。 node の decodeURI/decodeURIComponent だとUTF-8を期待されて動かない。ruby/pythonだと内部文字コード*1から変換が面倒くさい。nkf文字コードを変換を調べてたら、 nkf だけで行けることがわかった。

NKF で URL をデコードする

$ echo %E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%EF%BC%81 | nkf --url-input
こんにちは!

--url-input オプションを使えば、デコード出来る

デコード結果をさらに utf8にするには -W オプションをつけておけばいい。nkf --url-input -W

NKF でURLをエンコードする。

takuya@:~$ echo こんにちは! | nkf -MQ | sed s/=/%/g
%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%EF%BC%81

-MQ オプションはQuoted stream に変換するので、 =を使ってる。それを%に変換すればいい

CP932(MSP92/Shift-JIS) の%エンコード文字コードを扱うには

組合せて使います。

echo %82%B1%82%F1%82%C9%82%BF%82%CD | nkf -w  --url-input
こんにちは

nkf 便利。

NKFは枯れた技術だし安心して使えるわ。Windows文字コードがutf8にならねーかなぁ

関連資料

文字コード変換コマンドの nkfの使い方と実例をまとめました。 - それマグで!

参考資料

*1:ruby の場合内部文字コードはないんだけど、utf-8がデフォルト仕様なので、やっぱり面倒くさい

Macのopen(開く・保存)のダイアログで、不可視ドットファイル(フォルダ)を選択するーフルパスで開くモード

Mac の保存ダイアログで不可視フォルダを選びたい

開くダイアログのフォルダ選択のときに、隠しファイルやフォルダを開きたいときがよくある。

ドットファイルやドットのフォルダ( .rbenv / . pyenv など)を開きたい。

たとえば、atom/visual studio code/intelli J のIDEドットファイルを見たいときが結構ある。

私の場合 RubyMineやPycharm で rubygemspythonのpip ファイルを見たいときが頻発した。毎回コマンドで指定するのも面倒くさいので、なんか方法がないか調べたらあった。

⌘⇧G / Shift+Cmd+G でフルパス入力

保存・開くダイアログで上記のショートカットを入力すると、ダイアログが開いて、フルパスで指定できるようになる。

f:id:takuya_1st:20170612012219p:plain

残念ながら、補完は効かないようで・・・

フルパスを取得するには、いったんターミナルなどでフルパスを作ってクリップボードに入れておく必要がありますね。

Windows(田)のNTFSみたいに、フォルダ・ファイルごとに可視・不可視を切り替えらればいいのにね。APFSで導入されないかなー

rubymine で .rbenv を選ぶときに活躍した。

jetbranins の rubymine の nvm / rbenv と webstorm で .npm / nvm など、ドットファイル (dotfile) になったフォルダから インタプリタで実行バイナリを選ぶときにこの方法が活躍する

rubymine などで実行環境SDKで .rbenv が出てこない時があってそのとき、この方法によって Shift+Cmd+G を押してフルパスを入力しフォルダを移動して解決する。 f:id:takuya_1st:20200511085837p:plain

f:id:takuya_1st:20200511085840p:plain

参考資料

http://inforati.jp/apple/mac-tips-techniques/system-hints/how-to-use-move-to-folder-command-in-a-open-or-save-dialog-in-macos.html

Windowsはフォルダ毎に不可視を設定できる。

Windowsのホームディレクトリに出てくる、dotfiles を非表示にする。 - それマグで!

2020-05-11 追記

intellij で困ったので追記した。

pry のEchoをオフにする

コピペなどでエコーが邪魔なとき

_pry_.config.print = proc {}

irb の場合は

conf.echo = false

こうすれば、長いStringのスクロールで死ななくて済む

一時的にオフにして、元に戻すなら

_pry_.config._print = _pry_.config.print
_pry_.config.print = proc{}

元に戻す

_pry_.config.print = _pry_.config._print

これをトグルできる関数にしてくれると便利なんだけどな。

参考資料

https://github.com/pry/pry/wiki/Customization-and-configuration#Config_print

chrome でHTML をPDFに変換する

HTMLをPDFに変換する --print-pdf オプション

HTMLをPDFに変換するコマンドは、いくつか有るけれど、 chrome のオプションだけで実現できる。

しかも chrome59 から headless オプションがあって更に便利になった。

コマンドの使い方

chrome-bin --headless --print-pdf=path/to/output.pdf  input_url

input_url のところには、ブラウザで開けるものなら、大抵のものが入る。

ローカルファイルなども印刷するできる。

chrome-bin --headless --print-pdf=path/to/output.pdf  /path/to/index.html

mac os の場合、直接バイナリを指定する

macOS X の場合は .app の中身をたどって指定する必要がある。

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
 --headless\
 --print-to-pdf='/Users/takuya/Desktop/a.pdf' \
file:/Users/takuya/Desktop/sample.html

開けないURLはどうするのか

ログインが必要なURLなどはどうするのか。

Cookieを拾ってくるしか無い。Cookieはプロファイルに入ってるのでプロファイルから拾うしかない。

--user-data-dir=/Users/takuya/Library/ApplicationSupport/Google/Chrome/Default/"

プロファイルを指定することでCookieを拾えるのでそこから何とかする。ただし、プロファイルは起動時にロックが掛かるので、同時に複数のインスタンスで使用できない。その為に、セッションのCookieは扱うのがとても面倒なので、Chromeをいったん終了したら消えてしまうセッションCookieを扱うには、Chromeを強制終了したりSelenium側でAddCookieするとか面倒くさい処理がひつようになる。

参考資料

List of Chromium Command Line Switches « Peter Beverloo

Seleniumで印刷(print preview)を経てPDFを保存する方法

Selenium + chromedriverで 印刷プレビューにアクセスするのが面倒くさい

Chromeを webdriverでアクセスすると iframe で作られた、印刷プレビューにアクセスするのがとてもめんどくさい。(セキュリティ関連のアレコレの制限をdisableオプションで取っ払えば出来るんだろうけど)

HTMLを印刷したい。

たとえば、某銀行の印刷プレビューページなどをそのまま取りたいとか。印刷用のCSSが正しく動くかどうかとか、テストしたい箇所も山ほどある。

キオスクオプションが最強

1週間ほど毎日のように、あれこれ調べまくった結果、Chromeの起動オプションに –print-to-pdf がありました。しかしコレでは、「いま表示しているページ」を印刷するのが不便です。

Cookieを引き継ぐためにProfileを設定してChromeの再起動が必要です。

さらに探していたら、 --kiosk-printing とう「最高」なオプションを見つけたので歓喜しました。

--kiosk-printing とは?

印刷ダイアログが開くと、印刷ボタンを無条件に押してくれます。これはキオスクモードで、ユーザーにプリンタの選択をさせない為に作られているようです。

この印刷ボタンを無条件に押してくれるオプションを使うとHTMLをPDFで保存してくれます。

selenium で使うとき

Capabilitiesを活用します、そして該当ページへ移動したら、window.print() を実行します。

caps = Selenium::WebDriver::Remote::Capabilities.chrome(
      "chromeOptions" => {
          "args" => [
              '--kiosk-printing',
          ],
          "prefs" => {
              download: {
                  default_directory: '/path/to/download'
                  directory_upgrade: true,
                  prompt_for_download: false,
              }
          }
      })
driver = Selenium::WebDriver.for :chrome , :desired_capabilities => caps

driver.get 'chrome://version'
driver.execute_script(' return window.print();')

window.print で表示された、印刷ダイアログで、ボタンを押すことは kioskオプションがやってるくれるのでSelenium側では処理をする必要がありません。

保存先のディレクト

基本的には、保存先のディレクトリで指定したフォルダになりますが、設定が曖昧だと ~/Downloads に保存されます。

もし、設定がうまくいかないときは 、Seleniumで次のページへアクセスして、設定を変更したら間違いなくうまくいく。

driver.get 'chrome://settings'

参考資料

http://peter.sh/experiments/chromium-command-line-switches/

rubyのLoggerでログを出力する方法

ruby のロガーについて調べておきました

ruby ではログを出すときに Logger が便利です。

require 'logger'

logger = Logger.new(STDOUT)

標準出力に出す場合は STDOUT($stdout) 、標準エラー出力に出す場合は STDERR($strerr) を指定する。

ログを出す

logger をインスタンス化したら、ログを書き出す。

logger.info('Hello Log')
# => I, [2017-06-07T13:53:15.178750 #20342]  INFO -- : Hello Log

ログの出し方:ログレベルに応じたログを書く

log()のような関数はなく、ログレベルに応じたメソッドを使う。

ログレベルは、 debug, info, warn, error, fatal, unknown があり、それぞれが、メソッド名になっている。

logger.debug('メッセージ')
logger.info('メッセージ')
logger.warn('メッセージ')
logger.fatal('メッセージ')
logger.unknown('メッセージ')

まとめて実行してみる。 Object.send(:method_name, args )インスタンスメソッドを呼び出せるのでそれを利用する。

[:debug,:info,:warn,:error,:fatal,:unknown].each{|e| logger.send(e,"message at level #{e}") }

実行結果

>> [:debug,:info,:warn,:error,:fatal,:unknown].each{|e| logger.send(e,"message at level #{e}") }
D, [2017-06-07T13:55:36.802479 #20342] DEBUG -- : message at level debug
I, [2017-06-07T13:55:36.802532 #20342]  INFO -- : message at level info
W, [2017-06-07T13:55:36.802549 #20342]  WARN -- : message at level warn
E, [2017-06-07T13:55:36.802562 #20342] ERROR -- : message at level error
F, [2017-06-07T13:55:36.802574 #20342] FATAL -- : message at level fatal
A, [2017-06-07T13:55:36.802585 #20342]   ANY -- : message at level unknown

ログのレベル

ログのレベルは次のようになっていて、debug が一番弱い。

  1. debug
  2. info
  3. warn
  4. error
  5. fatal
  6. unknown

一番弱いのはdebug。 弱いとは、設定でログ書き出しを無視することが出来る。

LOG_LEVELが info なら debug は書き出されない。

ログレベルに応じてフィルタをする。

ログにはレベルがあって debug, info, warn, error, fatal, unknown の順になっている。

すべてのログを出力する(デフォルト)

デフォルトではすべてのログを出力する Logger::DEBUG(=0) になっていて、ログを出すとすべてが書かれる

require 'logger'
logger = Logger.new(STDOUT)
logger.level == Logger::DEBUG #=> true

レベルを INFO にする

INFOにすると、DEBUGのメッセージが無視される。

logger.level = Logger::INFO
[:debug,:info,:warn,:error,:fatal,:unknown].each{|e| logger.send(e,"message at level #{e}") }

実行結果( debug のメッセージは捨てられる)

I, [2017-06-07T14:01:51.257465 #20342]  INFO -- : message at level info 
W, [2017-06-07T14:01:51.257579 #20342]  WARN -- : message at level warn
E, [2017-06-07T14:01:51.257608 #20342] ERROR -- : message at level error
F, [2017-06-07T14:01:51.257712 #20342] FATAL -- : message at level fatal
A, [2017-06-07T14:01:51.257743 #20342]   ANY -- : message at level unknown

長めのメッセージを出力する

ブロックで渡せる

logger.info {  "現在のログレベルは " + logger.level.to_s + "です" }
#=> I, [2017-06-07T14:05:42.599811 #20342]  INFO -- : 現在のログレベルは 1です

時刻は別にいらないんだけど、短く出来る?

できる。

開発中とか時刻は別にいらないんだけどってとき

logger.datetime_format = '%Y-%m-%d %H:%M:%S'
logger.datetime_format = ''
logger.info("サンプル")
#=>I, [#20342]  INFO -- : サンプル

番号とか記号も決めたい

proc を渡せばO.K.

logger.formatter = proc do |severity, datetime, progname, msg|
   ">>>>>> #{msg}\n"
end
logger.info("サンプル")
# =>  >>>>>> サンプル

書式に意味有るの?

ある。ログ書式を元に、複数のサーバーからエラーログを集めたり、ログに基づいた通知をしたりする。

参考資料

https://docs.ruby-lang.org/en/2.0.0/Logger.html#class-Logger-label-How+to+close+a+logger

QRコードアプリはLINEのQRリーダーが一番手軽。( ios 10 まで

LINEのQRコードリーダが一番手軽って話。

QRコードのためだけに専用アプリを入れるのもめんどくさい。どれを選んだら良いか考えるのもめんどくさくないですか?

LINEについてるQRリーダで十分

QRリーダは、別にLINEだけの規格ではないので、一般的なサイトを開くQRコードであれば大抵は読めます

http://https:// もならほとんどが大丈夫です。

起動も簡単

起動もとても簡単です 3DタッチでPeekメニューを出せばいいので、LINEアイコンを押し込むだけです。ね?簡単でしょ?

f:id:takuya_1st:20170605174026p:plain

2017-06-20 追記

iOS 11 にQRリーダ搭載されたので、あと半年の命ですかね。3Dタッチ対応してるんだろうか。

ruby で先月の月末を求める

先月の月末を求めるには

まず、月初の01日を作ります。

Date.parse(Date.today.strftime('%Y-%m-01')).to_s

今月の1日を作る方法を知ってると後はなんでも応用が効くよね。

次に−1日する

(Date.parse(Date.today.strftime('%Y-%m-01'))-1).to_s

簡単でしょ?

strftime と parseが賢いので頼れば良いんだと思います。