ひよこになりたい

Programming Server Network Security CTF and so on

Macの任意のアプリの表示をショートカットキー1つでトグル切り替えできるようにする

Mac標準ターミナルをいつでもどこでも呼び出したい(表示・非表示を切り替えてすぐにターミナルを使いたい)と思い方法を色々探ってみたのですが、なかなかいい方法が見つからなかったのでAppleScriptスクリプトを書きKarabiner Elementsに設定することで実現したのでメモ。

Macの標準機能ではCmd+Hでウインドウを隠す動作が可能ですが、隠したあとウインドウを呼び戻すのは少し困難です。また、隠したウインドウを再表示することも難しいので、これまではiTerm2のような別ターミナルの機能で実現していました。

今回は、Terminalが最前面にあるときに、Cmd+`を押すと非表示になり、もう一度押すと最前面に戻ってくるような動作にしています。

これを応用してTerminal以外にも任意のアプリケーションに適用することができます。

前提

  • macOS
    • 今回は Mojave 10.14.6
  • Karabiner-Elements(Karabiner)
    • 今回は12.7.0

が使えること

方法

Scriptの作成

以下のApple ScriptをKarabinerの.config配下に保存します。

$ mkdir -p ~/.config/karabiner/scripts
$ vim toggle_terminal.script 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set name_of_app to "Terminal"

tell application "System Events"
    get name of application processes whose frontmost is true and visible is true
end tell

if Result contains name_of_app then
    tell application "System Events"
        set visible of process name_of_app to false
    end tell
else
    tell application "System Events"
        set frontmost of process name_of_app to true
        set visible of process name_of_app to true
    end tell
end if
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ためしに実行してみる

$ osascript ~/.config/karabiner/scripts/toggle_terminal.script
# Terminalが消える # 

set name_of_app to "Terminal" のTerminalのところを別の名前にしてもOK

これを任意のショートカットキーに紐付けるだけです。

Karabinerに登録

以下のファイルを作成します

$ vim ~/.config/karabiner/assets/complex_modifications/terminal.json
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
  "title": "スーパーすごいショートカット",
  "rules": [
    {
      "description": "TerminalのShow/Hide",
      "manipulators": [
        {
          "from": {
            "key_code": "grave_accent_and_tilde",
            "modifiers": {
              "mandatory": [
                "left_command"
              ]
            }
          },
          "to": [
            {
              "shell_command": "osascript ~/.config/karabiner/scripts/toggle_terminal.script"
            }
          ],
          "type": "basic"
        }
      ]
    }
  ]
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

KarabinerのJSON記述方法はおググりを🙏

あとはKarabinerのPreference>Complex Modifications>Add Rule>にターミナルの〜があるのでEnableにするだけ

補足

Apple Scriptむずい

7 Days to DieのLinuxサーバーを立てる

7 Days to DieというゲームをLinux Server上に置くための手順です。7 Days to DieはDedicated ServerとしてLinuxが使用できるのがいいですね。

OSはInstall済みなのが前提です。今回はCentOS7を利用しました。

ここも参考になるので詰まったら見てみてください

ディスクの用意

partedで適当に分割し、mkfsでext4のディスクを作る

[zip@satori ~]$ sudo parted -l
[sudo] password for zip:
Model: VMware Virtual disk (scsi)
Disk /dev/sda: 17.2GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      1049kB  1075MB  1074MB  primary  xfs          boot
 2      1075MB  17.2GB  16.1GB  primary  ext4


Error: /dev/sdb: unrecognised disk label
Model: VMware Virtual disk (scsi)
Disk /dev/sdb: 34.4GB
Sector size (logical/physical): 512B/512B
Partition Table: unknown
Disk Flags:

[zip@satori ~]$ sudo parted /dev/sdb
GNU Parted 3.1
Using /dev/sdb
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) p
Error: /dev/sdb: unrecognised disk label
Model: VMware Virtual disk (scsi)
Disk /dev/sdb: 34.4GB
Sector size (logical/physical): 512B/512B
Partition Table: unknown
Disk Flags:
(parted) mklabel msdos
(parted) mkpart primary ext4 0% 100%
(parted) q
Information: You may need to update /etc/fstab.

[zip@satori ~]$ sudo mkfs.ext4 /dev/sdb1

fstabに書いてマウント

[zip@satori ~]$ ls -la /dev/disk/by-uuid/
total 0
drwxr-xr-x. 2 root root 100 Aug  4 00:46 .
drwxr-xr-x. 5 root root 100 Aug  4 00:43 ..
lrwxrwxrwx. 1 root root  10 Aug  4 00:46 2eb3c8da-38f5-4a1e-8119-49a5cb4272a7 -> ../../sdb1
lrwxrwxrwx. 1 root root  10 Aug  4 00:45 3e2282e0-6444-4a96-864f-0c98fbe80674 -> ../../sda1
lrwxrwxrwx. 1 root root  10 Aug  4 00:45 68842a27-4a2c-4562-bcae-9e468c9b2f48 -> ../../sda2

[zip@satori ~]$ sudo vim /etc/fstab
UUID=68842a27-4a2c-4562-bcae-9e468c9b2f48 /                       ext4    defaults        1 1
UUID=3e2282e0-6444-4a96-864f-0c98fbe80674 /boot                   xfs     defaults        0 0
UUID=2eb3c8da-38f5-4a1e-8119-49a5cb4272a7 /7days                  ext4    defaults        0 0

[zip@satori ~]$ sudo mkdir -p /7days
[zip@satori ~]$ sudo mount -a
[zip@satori ~]$ sudo useradd sdtd -d /7days/
[zip@satori ~]$ sudo chown sdtd. /7days

メモリ状況の確認。一応それなりに重いと思うのでメモリ不足に備えるためswapを作っておく。今回はファイルベースにしました。

[zip@satori ~]$ free -m
              total        used        free      shared  buff/cache   available
Mem:           7823         139        7326           8         357        7416
Swap:             0           0           0

[zip@satori ~]$ sudo mkdir /swap
[zip@satori ~]$ sudo dd if=/dev/zero of=/swap/swapfile_8g bs=1M count=8192
8192+0 records in
8192+0 records out
8589934592 bytes (8.6 GB) copied, 32.5157 s, 264 MB/s
[zip@satori ~]$ sudo mkswap /swap/swapfile_8g
Setting up swapspace version 1, size = 8388604 KiB
no label, UUID=437a728a-872c-4659-94bb-83449500508f
[zip@satori ~]$ sudo swapon /swap/swapfile_8g
swapon: /swap/swapfile_8g: insecure permissions 0644, 0600 suggested.
[zip@satori ~]$ sudo chmod 0600 /swap/swapfile_8g
[zip@satori ~]$ free -m
              total        used        free      shared  buff/cache   available
Mem:           7823         145         129           8        7547        7342
Swap:          8191           0        8191
[zip@satori ~]$ sudo vim /etc/fstab
UUID=68842a27-4a2c-4562-bcae-9e468c9b2f48 /                       ext4    defaults        1 1
UUID=3e2282e0-6444-4a96-864f-0c98fbe80674 /boot                   xfs     defaults        0 0
UUID=2eb3c8da-38f5-4a1e-8119-49a5cb4272a7 /7days                  ext4    defaults        0 0
UUID=437a728a-872c-4659-94bb-83449500508f swap                    swap    defaults        0 0

swapをできるだけ使わないようにする。

[zip@satori ~]$ sudo vim /etc/sysctl.conf
vm.swappiness=1
[zip@satori ~]$ sudo sysctl -p
vm.swappiness = 1

Firewall設定

firewalldに設定を追加する。ポートは 26900/tcp。26900-26903/udpも公式では必須と書かれているけど、開放しなくても入れたので今回は設定しません

8081/tcpは管理コンソールなので締めておきましょう

[zip@satori 7days]$ sudo firewall-cmd --permanent --add-port=26900/tcp
success
[zip@satori 7days]$ sudo firewall-cmd --reload
success
[zip@satori 7days]$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens160
  sources:
  services: dhcpv6-client ssh
  ports: 26900/tcp
  protocols:
  masquerade: no
  forward-ports:
  sourceports:
  icmp-blocks:
  rich rules:

SteamCMDのInstall

SteamCMD - Valve Developer Community

[zip@satori ~]$ sudo yum install glibc.i686 libstdc++.i686
[zip@satori ~]$ sudo su - sdtd
Last login: Fri Aug  4 00:56:18 JST 2017 on pts/0
-bash-4.2$ mkdir Steam  # 決め打ち
-bash-4.2$ cd Steam/
-bash-4.2$ curl -sqL "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" | tar zxf -
-bash-4.2$ ./steamcmd.sh
Steam>login anonymous

Connecting anonymously to Steam Public...Logged in OK
Waiting for user info...OK

Steam>force_install_dir ../
Steam>app_update 294420 validate

Steam>quit

設定ファイルの編集

設定ファイルは基本的にはdefaultでOKですが、以下のパラメータは設定推奨です

  • ServerPassword
    • 完全オープンなサーバーにしたい以外は設定しておきましょう
  • SaveGameFolder
    • <!-- <property name="SaveGameFolder" value="absolute path" /> --> という記述があるので <!-- --> を削除して absolute path を設定しましょう
    • 7days to dieではデフォルトでは7days実行ユーザーの ~/.local/share/7DaysToDie/Saves/Navezgame/GameName の名前でディレクトリが切られ、そこにゲームデータが保存されます。
    • 何もしない場合、インストールディレクトリにはセーブデータは入らないので注意。ここで指定した場所に置かれるので、先程実行ファイルをインストールしたディレクトリのパスを記述しておきましょう
    • この記事の場合、/7days/ に7daysの実行ファイルが置かれるので、 value="/7days/" と記述しておくと実行ファイルが置かれたディレクトリにセーブデータが置かれます
-bash-4.2$ pwd
/7days
-bash-4.2$ ls
7DaysToDieServer_Data  7DaysToDieServer.x86_64  backup.sh  libstdc++.so.6  Saves             startserver.sh   steamapps
7DaysToDieServer.x86   backup_rotate.conf       Data       Licenses        serverconfig.xml  steam_appid.txt  steamclient.so
-bash-4.2$ cat serverconfig.xml | grep 'name="SaveGameFolder"'
        <property name="SaveGameFolder"                         value="/7days/Saves/" />  <!-- Use this to only override the save game path. Do not forget to uncomment the entry! -->
-bash-4.2$ ls /7days/Saves/
Navezgane  profiles.sdf  serveradmin.xml
-bash-4.2$ ls /7days/Saves/Navezgane/
7days Game
-bash-4.2$ cat serverconfig.xml | grep 'name="GameName"'
        <property name="GameName"                                               value="7days Game"/>
  • GameName
    • ↑で使われるので、わかり易い名前にしておきましょう
  • TelnetPassword / TelnetEnabled
    • 変更推奨

起動&systemd作成

起動のため、systemdに登録する

$ vim /etc/systemd/system/7days.service
[Unit]
Description=7 Days to die server

[Service]
User=sdtd
Group=sdtd
WorkingDirectory=/7days/
ExecStart=/bin/sh /7days/startserver.sh -configfile=serverconfig.xml
ExecReload=/bin/kill -HUP $MAINPID
Type=simple

[Install]
WantedBy=multi-user.target

設定ファイルをおいたら起動

$ sudo systemctl enable 7days
$ sudo systemctl start 7days

しばらくすると起動します。

Ramdisk上に置くには

以下のコマンドでramdiskを作成し、そこにインストール or データの移動をします

今回は16GBのramdiskを作成。fstabにも設定を入れ、起動時にramdiskを作成するようにする

$ sudo mkdir -p /ramdisk
$ sudo vim /etc/fstab
~略~
tmpfs       /ramdisk tmpfs   defaults,size=16384M   0 0
$ sudo mount -a

データの移動を行う場合は、 「設定ファイルの編集」のセクションでも記述した、 SaveGameFolder の場所を変更しましょう

移動しないと移動前のディスクを参照するためramdiskの恩恵を受けれません

backup

ramdiskに置く場合はbackupも設定しましょう(置かない場合も、だけど)

今回は3時間に一度backupをするスクリプトを設定します。niceで優先度を下げておきます

$ sudo yum install pigz -y
$ cd
$ vim backup.sh
#!/bin/sh

DST="/backups"
BACKUP_DAYS=3

cd /ramdisk/

DIRNAME=$(basename $(pwd))
NOW=$(date "+%Y-%m-%d-%H-%M-%S-%Z")

tar c . | pigz -p 8 > $DST/7days_backup_$DIRNAME_$NOW.tar.gz

# find "${DST}" -type f -ctime "+${BACKUP_DAYS}" -exec \rm -fv {} \; | logger  # DST内のBACKUP_DAYS日前以前のファイルをすべて削除するので注意

このスクリプトをsystemd.timerに登録。

$ sudo vim /etc/systemd/system/7days_backup.timer
[Unit]
Description=7 Days to Die backup timer

[Timer]
OnBootSec=3h
OnUnitActiveSec=3h
Unit=7days_backup.service

[Install]
WantedBy=multi-user.target

$ sudo vim /etc/systemd/system/7days_backup.service
[Unit]
Description=7 Days to Die backup service

[Service]
Type=simple
ExecStart=/bin/nice -n 10 /bin/sh /7days/backup.sh

[Install]
WantedBy=multi-user.target

backupの実行&timer set

$ sudo systemctl start 7days_backup  # 実行
$ sudo systemctl enable 7days_backup.timer  # timer set

これで設定できました

Python+Selenium+Chrome(+BeautifulSoup)でスクレイピングする

以前Python+Selenium+Phantom.js+Beautifulsoupでスクレイピングする - ひよこになりたいという記事を書きました。

zipsan.hatenablog.jp

当時はChromeを入れる必要がなく、バイナリを置くだけで使えるPhantom.jsが非常に便利でこれを使っていたのですが、去年、Phantom.jsのメンテナンスが終了するというニュースが発信され、記事も書き換えないとなあと思っていました。が、それから暫くの間はJavascriptをリアルタイム処理させる必要のないページばかりスクレイピングしていたので、結局放置したままでした(すみません)。

ここ1年の間に、ChromeのVersion59以降より標準で(stable版で)headlessモード(ブラウザ画面が立ち上がらないモード)が使えるようになったらしく、前のようにxvfbのような仮想スクリーンを使う必要もなくなったことに加え、久々にJavascriptが必要なサイトをスクレイピングする必要が出てきたため、この機会に使用法についてまとめておくことにします。

Phantom.jsの作者さんもChromeを使うとよろしーと言っているみたいですね。

環境構築

必要なもの

  • Python + pip(ここでは3.6.5を使いました)
  • Selenium
  • Google Chrome(Version59以上だったらOKです。)
  • ChromeDriver

OSはLinuxでもMacでも大丈夫です。多分Windowsでもいけます。私はArch Linux(GUIなし)を使いました。

インストール

  • Python+pip
    • 適当に入れておいてください
  • Selenium
    • pip install seleniumでインストール出来ます。
  • Google Chrome
    • Package管理ツールでいれてもいいですし、exeやdmg、直接rpmdebからいれてもいいです。
    • CentOSだったら CentOS7にChromeをインストール - Qiita あたりが参考になるかと思います。
    • Arch Linuxの場合は yaourt -S google-chrome-stable で入れれます。(私の場合はライブラリの依存関係が壊れていたので、起動時のエラーを見ながらdowngrade で頑張って3-4個のライブラリをダウングレードして起動まで持っていきました)
  • Chrome Driver
    • Downloads - ChromeDriver - WebDriver for Chrome からダウンロード出来ます。
    • ダウンロードして解凍しましょう。多分中にchromedriverというバイナリがあるはずです。適当なディレクトリに移動してておき、パスを通しておきましょう。
      • echo 'export PATH="$PATH:/path/to/chromedriver_directory"' >> ~/.bashrcとかで行けるんじゃないかなあ(未検証)

使ってみる

# -*- coding: utf-8 -*-
from selenium import webdriver

options = webdriver.chrome.options.Options()
options.add_argument("--headless")  # これ消せばブラウザ画面が出ます

driver = webdriver.Chrome(chrome_options=options)

driver.get("https://sukumizu.moe")

# タイトル
print(driver.title)

# URL
print(driver.current_url)

# cookies
print(driver.get_cookies())

# スクリーンショットの撮影
print(driver.save_screenshot("screenshot.png"))

# ページのソースの取得
print(driver.page_source)

Phantom.jsのときのように一通り欲しい機能は揃っていますね。

また、driver.page_sourceをBeautifulSoupに食わせれば以前のようにそのままBeautifulSoupの機能が使えますし、Seleniumにはそもそも要素の選択機能があるので、それを使ってスクレイピングすることも出来ます。

# id検索
driver.find_element_by_id('id')

# class検索
driver.find_element_by_class_name('classname')

# ネストされた要素の取得
driver.find_elements_by_xpath(".//div")

7. WebDriver API — Selenium Python Bindings 2 documentation

また、クリックや文字入力もできるので、もうなんでもやりたい放題って感じです。

UI操作はちょっと複雑なコードになるのでここでは割愛します。興味がある方は調べてみてください。

VSCode+Python+Jupyter Notebookでの開発環境を整える

機械学習(データ分析)をちょっと触りだけやってみようと思い、最近使い始めたVSCodeで環境構築をしてみました Jupyterを使ったことがなかったのでちょっと苦戦しましたが一応動いたので手順を書き記しておきます。 ついでにAnacondaについてくるJupyterを使う場合の手順も記述しておきます。

はじめに

Jupyter(Project Jupyter | Home)はWeb上で様々な言語を実行することのできるツールです。実行するとWebサーバーのようなものが立ち上がり、ブラウザでコードを書いてポチポチして実行できます。データ分析の世界ではメジャーなツールらしいです。

とはいえブラウザ上でコード書くのも微妙だし、毎回ブラウザに移動するのも面倒なのでエディタ上で完結できないか調べたところ、 拡張機能を使ってVSCode上でも実行結果を表示することができるようなので、今回はその環境を構築しました。

こんな感じ f:id:zipsan:20180321035002p:plain

今回はWindowsでやってみましたがたぶんMacとかLinuxでも同じかなと思います。

前提

上記の環境はすでに整っているものとします。入ってない場合はググって適当にインストールしてください

環境構築

Jupyterのインストール

anacondaの仮想環境(Anacondaのcondaコマンドによる仮想環境の使い方のまとめ - minus9d's diary)を入れている場合は不要です。

VSCode上でTerminalを開きます。標準の場合Ctrl+Shift+Pを押し、「python create terminal」でPythonのターミナルパネルを出します。使用するPythonを選択して以下のコマンドを実行します。 f:id:zipsan:20180321035028p:plain

# pipでインストール(anacondaを入れている場合は不要)
python -m pip install jupyter
or
pip install jupyter

# テスト
> jupyter notebook
[I 03:22:50.412 NotebookApp] Serving notebooks from local directory: C:\Users\@@@@
[I 03:22:50.413 NotebookApp] 0 active kernels
[I 03:22:50.413 NotebookApp] The Jupyter Notebook is running at:
(略)

f:id:zipsan:20180321035031p:plain

ワークスペースディレクトリの作成

どこかよしななところに開発用のディレクトリを作成します。今後の設定はこのディレクトリのみ有効になるので、環境が違っても安心です

Jupyterのタスク(バックグラウンド実行環境)の設定

タスク>タスクの構成

f:id:zipsan:20180321040016p:plain

テンプレートからtasks.jsonを生成 f:id:zipsan:20180321040019p:plain

Others 任意の外部コマンドを実行する例 f:id:zipsan:20180321040021p:plain

と進めます。

以下の内容をtasks.jsonに記述します。 "cwd": "R:\\test"の部分は先程作った開発ディレクトリのパスを指定してください。

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Run Jupyter Notebook",
            "type": "shell",
            "command": "cmd.exe",
            "args": [
                "/C",
                "'jupyter notebook'"
            ],
            "group": "none",
            "options": {
                "cwd": "R:\\test"
            },
            "problemMatcher": []
        }
    ]
}

Mac/Linuxの場合は、commandの部分をbash、argsの部分を

"args": [
    "-c",
    "'jupyter notebook'"
],

になるのかなあと思いますが未検証です(検証後追記します)

参考:VSCodeのタスクでjupyter notebookを起動する - Qiita

また、anacondaの仮想環境で実行したい場合はargsの部分を以下のように記述すればOKです。

"args": [
    "/C",
    "'C:\\Users\\[ユーザー名]\\Anaconda3\\Scripts\\activate [仮想環境名] & jupyter notebook'"
],

Jupyterの実行

記述が終わったらタスクの実行をします。

Ctrl+Shift+Pで「task run」と検索して「タスク:タスクの実行」を選ぶ f:id:zipsan:20180321041710p:plain

「Run Jupyter Notebook」を選ぶ f:id:zipsan:20180321041735p:plain

するとJupyterが起動します。選択部分のURLが必要になるのでコピーします。 f:id:zipsan:20180321041827p:plain

Ctrl+Shift+Pで「jupyter enter」と検索し、「Jupyter: Enter the url~」を選ぶ f:id:zipsan:20180321042037p:plain

先ほどコピーしたURLを貼り付けてEnter f:id:zipsan:20180321042159p:plain

これで環境は整いました。

(Option)キーバインドの設定

実行を楽にしたい場合はキーバインドの設定をします。

Ctrl+Shift+Pで「shortcuts」と検索し「基本設定:キーボードショートカットを開く」を選ぶ f:id:zipsan:20180321042417p:plain

高度なカスタマイズを行うには~の keybindings.json を押す f:id:zipsan:20180321042549p:plain

次のように入力し、保存

[
    {
        "key": "ctrl+e ctrl+j",
        "command": "jupyter.execCurrentCell",
        "when": "editorTextFocus"
    }
]

keyのところはご自由にどうぞ

f:id:zipsan:20180321042420p:plain

実行してみる

ディレクトリの中に pythonファイルをつくって、以下を記述。 matplotlibやnumpyがない場合はエラーになります

#%%
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np

x = np.linspace(0, 20, 100)
plt.plot(x, np.sin(x))
plt.show() 


#%%
print("Hello")

うまく言っている場合は #%% の直前に Run cell とでていると思います。

#%% で区切られた部分が1つのセクションとなるので、その中のどこでも良いのでカーソルを移動し、 Ctrl+Shift+Pから「Jupyter run cell」を実行します。(キーバインドの設定をした場合はそれを押せばOK)

カーソルが上のセクションを指定している場合はグラフが表示され f:id:zipsan:20180321043407p:plain

下を指定している場合はHelloが出力されます。 f:id:zipsan:20180321043410p:plain

matploitlibなどがない場合はModuleNotFoundErrorとなりますが、ひとまずこれで実行できるようになりました。

SyslinuxでUSBメモリからWindowsインストールメディアを起動する

大学のメディアを使うときにちょっと詰まったのでメモ
コピペでできるように書いておきます
USBメモリ/インストールメディアに限定した話ではないけど、よく使うのがUSBメモリなのでとりあえずタイトルはこれで。

Arch Linuxで作ります。Ubuntuとか他のLinuxでも同じ感じでできるはず

必要なもの:

環境設定(Arch)

$ sudo pacman -S syslinux
$ sudo pacman -S dosfstools  # mkfs.vfat用
$ sudo pacman -S parted  # fdiskでもOK

USBのフォーマットとパーティショニング

まずUSBメモリを特定する。適当に以下のコマンドを駆使して目星をつける。

$ sudo fdisk -l
$ lsblk
$ dmesg  # USBを挿してすぐに見てみる 

今回は/dev/sdkがUSBでした。

次にフォーマットとパーティショニング。partedを使う。
USBの中身は完全に消去されるので注意

$ sudo parted /dev/sdk
(parted) p
(parted) mklabel msdos
(parted) mkpart primary fat32 0% 100%
(parted) set 1 boot on
(parted) p
(parted) quit

ブートフラグを立てておく。

作成した/dev/sdk1をfat32でフォーマット 

$ sudo mkfs.vfat /dev/sdk1

インストールメディアの書き込み

USBメディアとisoメディアをマウントしてisoのファイルをUSBにコピー。

$ sudo mkdir /mnt/{iso,usb}
$ sudo mount -o loop ~/path_to_iso/Win_Installer.iso /mnt/iso
$ sudo mount -o rw /dev/sdk1 /mnt/usb
$ sudo cp -r /mnt/iso/* /mnt/usb/

おそらく/mnt/usb/boot/ができているはず...

Syslinuxをいれる 

Syslinuxの本体のコピーとインストール

$ sudo mkdir /mnt/usb/boot/syslinux
$ sudo cp -r /usr/lib/syslinux/bios/*.c32 /mnt/usb/boot/syslinux/
$ sudo extlinux --install /mnt/usb/boot/syslinux

これだけでは起動できないのでmbrを書き込む

$ sudo dd if=/usr/lib/syslinux/bios/mbr.bin of=/dev/sdk bs=440 count=1 conv=notrunc

設定ファイル(syslinux.cfg)がないので作成する 

$ cd /mnt/usb/boot/syslinux/
$ sudo vim syslinux.cfg
--------- vim ---------
PROMPT 1
TIMEOUT 30
DEFAULT menu.c32

LABEL BOOTMGR
        MENU LABEL ^Windows-installer
        COM32 /boot/syslinux/chain.c32
        APPEND fs ntldr=/bootmgr
-----------------------

Windowsは/bootmgrを呼び出す必要があるみたいなので、chain.c32のオプションのntdlrで指定する。
bootmgrはWindows Vista以降で使われるブートローダー。
chain.c32はチェインロードを可能にするモジュール。syslinuxからbootmgrへとチェインロードする。
fsはパーティションを検出してくれる(らしい。よくわからないけど、消すとbootmgrを読み込んだあとエラーで落ちた)
ntldrはWindowsブートローダーをロードするchain.c32のオプション。

Comboot/chain.c32 - Syslinux Wiki

あとかたづけ

$ cd
$ sudo umount /mnt/usb
$ sudo umount /mnt/iso

これで終了 qemu-KVMでは無事インストーラーが起動しました。 boot:が表示されて3秒後に起動するけど、起動しない場合はmenuと打ってみるといいかも?