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

2020年4月12日日曜日

Emacs batch mode と HTML解析

前提

  • たくさんあるhtmlファイルの加工、編集をしたい。
  • 環境はWindows 10.
  • Emacsは入ってます。バージョン26.3.
  • MSYS2も入っていてBash使用可能。
  • しかしPython等のお手軽スクリプト言語の実行環境は無し。MicrosoftのPowershellやその他スクリプト言語には不慣れ。

ということでEmacsのDOM処理用関数を使うワンライナーを書くことにしました。


例題

カレントディレクトリにある拡張子htmlのファイルを開いてid="my-content"をもつ要素だけを抽出し、テキスト化して拡張子.txtのファイルに保存する、というもの。

for f in *.html; do
/c/Users/${user}/local/emacs-26.3-x86_64/bin/emacs --batch $f --eval='(princ (dom-texts (dom-by-id (libxml-parse-html-region (point-min) (point-max)) "my-content") "\n"))' > $f.txt;
done
  • "/c/Users/${user}/local/emacs-26.3-x86_64/bin/emacs": Windows上のemacsコマンドのパス
  • "--batch": Emacsバッチモード。バッチモードの定義は下記参考ページに書いてある。大雑把には、普段「バッファ」や「ウィンドウ」を使用するEmacsの入出力関数(message, princなど)を標準入力や標準出力、標準エラー出力に結び付けて、非インタラクティブに処理を実行する。
  • "--batch"直後の$fは処理対象のhtmlファイルで、非インタラクティブなEmacsはこのファイルを開いてバッファに読み込む。
  • "--eval"の引数としてelispコードを渡す。この例ではhtmlを開いたバッファ全体を"libxml-parse-html-region"関数に渡してDOM化し、次のそのDOMから"my-content"というidをもつ要素を"dom-by-id"関数で選び、選ばれた要素を"dom-texts"関数に渡してテキスト部分を抽出して"princ"で出力している。どの関数もEmacs標準のものだから外部のelispは利用していない。

2015年5月6日水曜日

出力をクリップボードにリダイレクトする方法(clip, xclip)

Windows で作業をしていて初めて知った("clip"コマンド)。Linux/Unix の世界にも同様のコマンドがあった("xclip")。知ってよかった。

C:\Users\foo>date /T | clip

2013年12月8日日曜日

bash の wait コマンド(shell builtin command)

今日まで存在を知らなかった。。。バックグラウンドプロセスが終了するまで待ち合わせするコマンド。

惰性で順次実行してたシェルスクリプトを手軽に並行実行できるようになって効率上がるかも。

環境
$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin10.0)
Copyright (C) 2007 Free Software Foundation, Inc.
$ help wait
wait: wait [n]
    Wait for the specified process and report its termination status.  If
    N is not given, all currently active child processes are waited for,
    and the return code is zero.  N may be a process ID or a job
    specification; if a job spec is given, all processes in the job's
    pipeline are waited for.
例1) wait なし
$ cat test.sh 
#!/bin/bash
date
(sleep 1; echo 'sleep 1') &
(sleep 2; echo 'sleep 2') &
(sleep 3; echo 'sleep 3') &
date

$ ./test.sh 
2013年 12月 8日 日曜日 23時03分12秒 JST
2013年 12月 8日 日曜日 23時03分12秒 JST
sleep 1
sleep 2
sleep 3
バックグラウンドプロセスの終了を待たずに2つ目の date コマンドが実行されて日時を出力。その後1、2、3秒ごとに echo の結果が。
例2) wait あり
$ cat test.sh 
#!/bin/bash
date
(sleep 1; echo 'sleep 1') &
(sleep 2; echo 'sleep 2') &
(sleep 3; echo 'sleep 3') &
wait
date
$ ./test.sh 
2013年 12月 8日 日曜日 23時06分58秒 JST
sleep 1
sleep 2
sleep 3
2013年 12月 8日 日曜日 23時07分01秒 JST
全バックグラウンドプロセスの実行&終了を待ってから2つ目の date コマンドが実行された。合計3秒待ったから3秒後の日時がプリントされた。

2013年10月26日土曜日

bashでタブの出力:echo と printf

echo
$ echo -e "foo\tbar"
foo bar
printf
$ printf "foo\tbar\n"
foo bar

ただし、環境によっては echo の '-e' オプションが使えないとの意見あり(シェルの仕様に依存する)。

2013年9月19日木曜日

bash の brace expansion で数列生成できる

中括弧(brace)を使ったイディオム、たとえば

$ cp /foo/bar{,.orig}
はよく使っていた。でも数列まで扱えるとは知らなかった。

数列を作るときは seq コマンドを使って

seq 1 10
などと打っていた。

これも間違いではないが、中括弧を使えば seq 無しで、すなわち、

{1..10}
と書けるのだった。おそらく中括弧を使ったほうがスッキリきれいに書ける場面が多いだろう(キーボードを打つ回数だけ比較したらあまり変わらないかもしれないが。。。)

この brace expansion で数列を作る具体例のほとんどは「LinuxTips 連番ファイルをコマンド一発で作成する」に書いてあるのであまり付記することは無い。強いて挙げるならば、増分(increment)も指定できる点。以下がその例。

$ echo {1..10..2}
1 3 5 7 9
$ echo {z..a..5}
z u p k f a



2013年1月27日日曜日

psコマンドの結果をgrepするときのtips

こじんまりした話題だが、、、grepコマンド自身がプロセスのリストに表示されるのがわずらわしいとき、いちいち「grep -v grep」を通してた。これは正規表現を使って簡潔にできる。

tips適用前
ps aux | grep mingetty | grep -v grep
適用例1
ps aux | grep mingett[y]
適用例2
ps aux | grep [m]ingetty

昔から脈々と受け継がれているらしい。2006年にはブログに書いている人がいるから。

ちなみに自分の場合は「プロのためのLinuxシステム・10年効く技術」という本で知りました。

2012年9月10日月曜日

CentOS-5 起動スクリプトのスケルトン

'/etc/init.d/' に入れるスクリプトを書こうと思ったとき、そのひな形(スケルトン、テンプレート、等々)を求めてついインターネットを検索してしまう。しかし、無駄にエネルギーを消費する必要はない。システムにあらかじめインストールされているのだった。

そのパスは、'/usr/share/doc/initfiles-x.y.z/sysvinitfiles' のあたり(CentOS の場合)。

2012年8月10日金曜日

2012年5月27日日曜日

wget の '--spider' オプションはHEADメソッド

こちら wget –spider = Head Request : alexking.org の記事について。


自分の場合、ブックマーク(リンク集)のリンク切れをまとめてチェックしたいときにwget の '--spider'オプションを使う。このような利用方法のときは特に気にすることはないのだが、何らかのWebアプリケーションを実行したい場合には注意が必要とのこと。

というのは 'wget --spider' がHEADメソッドを実行するよう実装されているので、Webアプリのコードが実行されないことがあるらしい(サーバーの環境や設定に依存するみたいだが)。

GETでアクセスしつつ、ダウンロードされたファイルを自動的に削除したい場合には、'--delete-after'オプションを使うのがよい。

NetHogs - プロセスごとのデータ転送量をtop風に表示

既存のネットワークアプリの転送量を調べるときに使ったソフト。サーバーでこの NetHogs を起動しておいて、クライアント側でアプリのシナリオとかユースケースを1つ実行。サーバーのほうの画面で何バイト送受信したかを見て記録しておく。「なるほどこのシナリオの場合はx[KB]くらい通信するのか」と、だいたいの数字が分かる。

特徴は、転送速度(KB/sec)だけでなく、転送量の累積値が表示されるところ。たぶん初期状態では KB/sec の表示になっているが、実行中に m キーを押せば表示モードが KB/sec, KB, MB, B とサイクリックに切り替わる。

インストールに関しては、libpcap と ncurses に依存している。今回の環境(CentOS-6.0)では、epelリポジトリから yum でインストールできたので特に問題無し。


表示の例

テキトーに sshd と apache にアクセスした場合のキャプチャを貼り付けておく。

まずは Byte単位の表示。

プロセスのIDごとに、USER, PROGRAM, DEV, SENT, RECEIVED が表示される。シンプル。

それから KB/sec 単位の表示。


Windows バッチファイル FOR文での「コマンド置換」

Windowsの .bat ファイルを書いた。そして、dir等のコマンドの出力を、FOR文のパラメータとして指定する方法を知った。


.batファイルの例
拡張子 xml のファイル名を降順ソートで列挙し、後続のコマンド(ここでは単なる echo)に渡すFOR文。

@echo off
for /F "usebackq" %%file IN (`DIR /B /-N *.xml`) DO @echo %%file


Unix系のシェルで言うところのコマンド置換(command substitution)。バッククォート(`)を使う点は共通だ。


2012年3月4日日曜日

GPG で表示される "2048R" や "usage: SC", "usage: E" の意味

GnuPGで '--edit-key' オプションを使うと鍵の管理作業のためのメニューが出てくる。

$ gpg --edit-key 549B5813
gpg (GnuPG) 2.0.14; Copyright (C) 2009 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There in NO WARRANTY, to the extent permitted by law.

Secret key is available.

pub 2048R/549B5813  created: 2012-01-22  expires: never     usage: SC
                    trust: ultimate      validity: ultimate
sub 2048R/6878DE41  created: 2012-01-22  expires: never     usage: E
sub 2048g/60ACA1A9  created: 2012-01-22  expires: never     usage: E
sub 2048D/29641C08  created: 2012-01-22  expires: never     usage: S
(略)

ここで表示される "2048R" とか "usage: SC" の意味を理解しないでいるとまずそうだから調べてみた、という話。


2048R

これは "The GNU Privacy Handbook" に書いてあった。

The public key is displayed along with an indication of whether or not the private key is available. Information about each component of the public key is then listed. The first column indicates the type of the key. The keyword pub identifies the public master signing key, and the keyword sub identifies a public subordinate key. The second column indicates the key's bit length, type, and ID. The type is D for a DSA key, g for an encryption-only ElGamal key, and G for an ElGamal key that may be used for both encryption and signing. The creation date and expiration date are given in columns three and four. The user IDs are listed following the keys.

要するに数字の部分が鍵のビット長、残りのアルファベット1文字が鍵の種類を表す。R なら RSA、D なら DSA、g なら 暗号化専用の ElGamal、G なら 暗号化と署名両方に使える ElGamal(このハンドブックは1999年の古いものなのでRSAについて言及していないが)。

"2048g"


usage: SC とか

なんとなく "S" は Sign で "E" は Encrypt だろうと予想が付いているものの、調べてみると同じ疑問をもった人がいた。

How are the GPG usage flags defined in the key details listing? - Unix and Linux - Stack Exchange

回答によれば "S" が "for signing", "E" が "for encrypting", "C" が "Creating a certificate"(たとえば Revocation certificate: 失効証明書とか?), "A" が "authentication"とのこと(SSHやTLSにおける認証で使えるらしい)。


2012年3月1日木曜日

dd コマンドでファイルを読み書き

ddコマンドはディスクのバックアップやダンプに使われることが多いので、コピー専用のコマンドだと思っていたことがある。

実際はそうではなくて、もっと軽い用途、たとえば標準入力から読み込んだ内容をファイルに書き込んだり、ファイルを読み込んで標準出力に出力したりすることもできる。


入力した内容をファイルに出力
'of'オプションで出力先を指定しつつ ddを実行すると入力待ちになる。そこで任意の文字とEOF(Ctrl-D)を入力すれば、ファイルができる。
$ dd of=hello.txt
hello, world
0+1 records in
0+1 records out
13 bytes transferred in 2.835518 secs (5 bytes/sec)
$ cat hello.txt
hello, world
$
ファイルの内容を表示
'if'でファイルを指定するだけ。
$ dd if=hello.txt 
hello, world
0+1 records in
0+1 records out
13 bytes transferred in 0.000138 secs (94173 bytes/sec)
$
ディスクなどのブロックデバイスファイルの場合も同様に表示できる。ただしサイズが大きいので 'bs' や 'count' オプションで調節する。
$ sudo dd if=/dev/disk0 bs=5 count=1  # MacOS requires root privilege to read /dev/disk0
?1???1+0 records in
1+0 records out
5 bytes transferred in 0.000334 secs (14969 bytes/sec)
$

2012年2月27日月曜日

iノード番号で find

findコマンドには、inode 番号を指定するオプション '-inum' がある。


find /root/ -inum 261232
/root/.bash_history

このオプションは、今日「SELINUXシステム管理」という本を読んで知った(アクセス拒否の際 audit.log に対象のファイルのinode番号が出力されるので、inode番号からファイルを検索できると便利だよ、との文脈で)。


2012年1月15日日曜日

ハードディスクエラーとSMARTのPending sector, reallocated sector

SMARTで"Current Pending Sector Count"が検出されたときに、どう対応すればよいかという話。


Pending sector と reallocated sector、remap の概要

"Pending Sector"は、一言で言うと「不安定なセクタ」。次にアクセスしたときに正常に読み込める可能性もあるので"Remap"は行われないが、Remapされずにずっと不安定なままOSから参照されると dmesg等のログに "1 Currently unreadable (pending) sectors" といったエラーが出力され続けることがある。

エラーを解消するには、セクタをPending状態からremapされた状態、つまり"Reallocated sector"に変化させる必要がある。そのためには、セクタに対して一度書き込みを行えばよい。書き込みを行うことにより"Pending"の状態から"Reallocated"の状態に変化し、remapが行われるようになってエラーが解消する。同時に、SMARTの"Current Pending Sectors Count" が減り、"Reallocated Sectors Count"が増える。

ただし、エラーが解消する代わりにRemap処理はディスクアクセスの性能を落とす可能性がある(論理的に連続している情報が物理的には離れたトラックに配置され、磁気ヘッドのシーク時間が増えるため)。


対応方法

参考ページに書いてある。"hdparm --write-sector /dev/x" を使う方法と "dd if=/dev/zero of=/dev/x bs=4096 count=1 seek=y" を使う方法の二通りがあるが、前者のほうがLBAを直接指定すればよいので簡単かな、と。


Mac OS X: diskutil -- Modify, verify and repair local disks.

Mac OS にインストールされている、ディスクユーティリティコマンド。ディスク状態の確認、パーティションの作成、マージなどに使える。

diskutil によると、このコマンドはAppleが用意したもので、普通のBSDには入っていないらしい。


自分が使ったものだけメモしておく。

diskutil list
ディスクと、ディスク内のパーティションを一覧表示。
$ diskutil list
/dev/disk0
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *250.1 GB   disk0
   1:                        EFI                         209.7 MB   disk0s1
   2:                  Apple_HFS Macintosh HD            249.7 GB   disk0s2
/dev/disk1
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:        CD_partition_scheme Gateway                *442.3 MB   disk1
   1:                      CD_DA                         75.3 KB    disk1s0
   2:                      CD_DA                         83.6 MB    disk1s1
   3:                      CD_DA                         23.5 MB    disk1s2
   4:                      CD_DA                         117.1 MB   disk1s3
   5:                      CD_DA                         51.5 MB    disk1s4
   6:                      CD_DA                         50.7 MB    disk1s5
   7:                      CD_DA                         115.8 MB   disk1s6
SATAのHDD(disk0)と、CD-ROM(disk1)を認識しているのが分かる。
disk0 は"GUID_partition_scheme"というTYPEになっているので、MBRではなくGPTが書かれているのが分かる。
disk1 のほうは"Gateway"という名前になっているが、これは "Amazon.com: Gateway: John Abercrombie, Dave Holland, Jack Dejohnette: Music" という音楽作品である。
diskutil info
ディスクまたはパーティションの詳細情報を表示。次の実行例は、"SMART"情報だけを grep したもの。
$ diskutil info disk0|grep SMART
   SMART Status:             Verified
diskutil mergePartitions
パーティションをマージする。ファイルシステムと名前、マージするパーティション(複数)を引数で与える。最初に指定したパーティション以外のパーティションは消える。"JHFS+" は Journaled HFS+ のこと。
# diskutil mergePartitions JHFS+ new disk0s2 disk0s3


2011年12月30日金曜日

VMware Fusion のホストオンリーネットワークはハブのように振る舞う(スイッチではないみたい)

VMware Fusionで複数のVMをホストオンリーネットワークに接続し、VMのひとつで tcpdump を動かしてみる。そうすると、ブロードキャスト以外のパケットまで見えることに気づく。まるでリピータハブに接続したときのように。


環境

  • MacOS 10.6.8
  • VMware Fusion 4.1.1

VMを3つ作って(OSは、tcpdump や ping が使えるなら何でもよい)、それらのNICをホストオンリーネットワークにつなぐ。


ホスト(MacOS)で認識されているNICのうち、"vmnet1"がVMwareのホストオンリーネットワーク用の仮想ネットワークアダプタ。以下のように、ネットワークアドレスは"192.168.105.0"になっている。


$ ifconfig vmnet1
vmnet1: flags=8863 mtu 1500
 ether 00:50:56:c0:00:01 
 inet 192.168.105.1 netmask 0xffffff00 broadcast 192.168.105.255

なので、VMを起動するとVMのNICには"192.168.105.128/24" や "192.168.105.129/24" などが設定される。


$ ip addr show eth0
2: eth0:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:0a:48:1b brd ff:ff:ff:ff:ff:ff
    inet 192.168.105.128/24 brd 192.168.105.255 scope global eth0

準備ができたら、まず 1つのVMで "tcpdump -i eth0" を実行し、残り2つの VM間で ping をしてみる。すると tcpdump の出力に ping による通信が出てくる。

次に、プロミスキャスモードOFFの'-p'オプションをつけて tcpdump を実行して、同様に ping を実行すると、今度は出てこない。プロミスキャスモードが効く、つまり switched network には接続されていないときの動作になっている。


物理的な環境だとスイッチ(ングハブ)を常に使うから、VMware Fusionの世界もスイッチだと思い込んでいたが、違うらしい。また、VMwareのエディション等によっても挙動が変わってくる模様。


2011年12月26日月曜日

OpenSSHサーバーの鍵生成

一般的なLinuxディストリビューションでは、OpenSSHサーバーがインストールされていて、起動すればすぐに使える状態になる(はず)。

しかし、いったいサーバーの鍵はいつどこで誰が準備したのだろうか? たぶんこんなこと気にする必要は無い。でも気になった。

CentOS-6.0 について言えば、sshdの起動スクリプトの中で自動的に3種類の鍵、つまり RSA1 と RSA(SSH2対応RSA),DSAの鍵が作られるのだった。

/etc/init.d/sshd から抜粋

(略)
KEYGEN=/usr/bin/ssh-keygen
SSHD=/usr/sbin/sshd
RSA1_KEY=/etc/ssh/ssh_host_key
RSA_KEY=/etc/ssh/ssh_host_rsa_key
DSA_KEY=/etc/ssh/ssh_host_dsa_key
(略)
        if test ! -f $RSA1_KEY && $KEYGEN -q -t rsa1 -f $RSA1_KEY -C '' -N '' >&/dev/null; then
(略)
        if test ! -f $RSA_KEY && $KEYGEN -q -t rsa -f $RSA_KEY -C '' -N '' >&/dev/null; then
(略)
        if test ! -f $DSA_KEY && $KEYGEN -q -t dsa -f $DSA_KEY -C '' -N '' >&/dev/null; then
(略)

'ssh-keygen'コマンドを素直に3回実行するという流れ。