Django プロジェクトを XServer で立ち上げる
どうも,筆者です.
ローカル環境で Django を用いた Web サーバを立てて利用している.そんな中,作成したサイトを外部に公開したい欲が出てきた.
ここで,作成したサイトは,Docker を用いて環境構築を行っていた.しかし,XServer では,Docker が利用できないため,1 から環境構築を行う.
今回は,XServer を対象に,Django で作成したサイトを外部公開するまでの試行錯誤の結果を残しておく.
前提
ここでは,Django プロジェクトの作成方法は解説しない.すでに,ローカル環境で動作確認が完了していることを前提に話を進める.
また,ドメイン,サブドメインの取得,SSL設定,SSH接続の設定,データベースの設定も完了していることを前提に話を進める.この辺りの情報は,公式サイトのマニュアルに丁寧に説明があるため,そちらを参照していただきたい.
説明の都合上,ドメイン名やプロジェクト名などの情報を以下に示す.ここでは,以下の内容をもとに環境構築を行う.実際に反映する際は,各自の環境に合わせて内容を修正すること.
ドメイン名・サブドメイン名
項目 | 設定値 |
---|---|
ドメイン名 | example.com |
サブドメイン名 | sample.example.com |
データベース
項目 | 設定値 |
---|---|
データベースのバージョン | MySQL 5.7 |
データベース名 | xs123_testdb |
アクセス権所有ユーザ | xs123_tester |
アクセス権所有ユーザのパスワード | dbpass |
ホスト名 | mysql123.xserver.jp |
文字コード | utf8 |
Django プロジェクトと CGI の設定
項目 | 設定値 |
---|---|
プロジェクト名 | test_project |
アプリ名 | test_app |
プロジェクトの親ディレクトリまでの絶対パス | ~/example.com/public_html/sample/django |
.htaccess ファイルの絶対パス | ~/example.com/public_html/sample/.htaccess |
index.cgi ファイルの絶対パス(パーミッションは 755) | ~/example.com/public_html/sample/django/index.cgi |
作業の流れ
- XServer にアクセスし,環境構築を行う.ここでは,MySQL に接続するための設定と pipenv のインストールを行う.
- 仮想環境を構築し,必要なライブラリをインストールする.
- settings.py を修正し,migration を行う.
- CGI の設定を行い,Django で作成した Web サイトに外部から公開できるようにする.
- static ファイルや media ファイルを配置し,Admin 管理サイトが整形された状態で表示されるようにする.
参考サイト
今回の作業を行う上で,以下のサイトを参考にした.
sunnyday-travel-aso-6487.ssl-lolipop.jp
環境構築
Linuxbrew のインストール
まず,Tera Term を用いて,XServer にアクセスする.そして,公式サイトを参考に,以下のコマンドを実行し,Linuxbrew をインストールする.
# GitHub 経由でデータを取得 git clone https://github.com/Homebrew/brew ~/.linuxbrew/Homebrew # brew コマンドにシンボリックリンクを張る mkdir ~/.linuxbrew/bin ln -s ~/.linuxbrew/Homebrew/bin/brew ~/.linuxbrew/bin # 環境変数の反映(詳細は不明) eval $(~/.linuxbrew/bin/brew shellenv) # 動作確認 brew help
python のインストール
brew コマンドを用いて,python をインストールする.ここでは,python3 をインストールした.
# python3 のインストール brew install python3 # 動作確認 python3 -V # 出力結果:Python 3.9.4 pip3 -V # 出力結果:pip 21.0.1 from /home/xs123/.linuxbrew/opt/python@3.9/lib/python3.9/site-packages/pip (python 3.9)
mysql-connector-c をインストールする準備
MySQL へのアクセスに必要なライブラリをインストールする.XServer の GCC のバージョンが古いためか,既存の libstdc++.so.6 ではエラーが発生し,インストールができなかった.
具体的には,以下のようなエラーが発生した.
Error: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found
ここでは,GCC をソースコードからビルドすることで,この問題を回避する.
GCC のコンパイル
brew を導入した際に GCC 5.5.0(厳密には,GCC 5.5.0_6) がインストールされていた.このため,GCC 5.5.0 のソースコードを対象に作業を行う.
参考サイトをもとに,以下のコマンドを実行し,GCC のビルドを行う.
# 作業用ディレクトリの作成 mkdir ~/workdir cd ~/workdir # ================= # ソースコードの取得 # ================= # GCC 5.5.0 のソースコードの取得 curl -LO http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-5.5.0/gcc-5.5.0.tar.gz # checksum のデータを取得 curl -LO http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-5.5.0/sha512.sum # checksum の確認(「gcc-5.5.0.tar.gz: 完了」となっていれば問題ない) sha512sum --check sha512.sum # 出力結果: # gcc-5.5.0.tar.gz: 完了 # sha512sum: gcc-5.5.0.tar.xz: そのようなファイルやディレクトリはありません # gcc-5.5.0.tar.xz: オープンまたは読み込みに失敗しました # sha512sum: 警告: 一覧にある 1 個のファイルが読み込めませんでした # ================== # GCC 5.5.0 のビルド # ================== # 圧縮ファイルの展開 tar xzfv gcc-5.5.0.tar.gz cd gcc-5.5.0/ # コンパイルに必要なライブラリの取得 ./contrib/download_prerequisites # ビルド用ディレクトリの作成 mkdir build cd build # Makefile の作成(ビルドのみのためprefixは使わないが,念のため設定) ../configure --enable-languages=c,c++ --prefix=/home/xs123/.linuxbrew --disable-bootstrap --disable-multilib # ビルド(20分くらいかかる) make
ライブラリのコピー
ビルドが完了したら,以下のファイルが存在することを確認する.これらのライブラリを brew でインストールされているパスにコピーする.
# ========================= # 生成されたライブラリの確認 # ========================= # build directory 以下で確認 ls x86_64-unknown-linux-gnu/libgcc/libgcc_s.so.1 # 出力結果:x86_64-unknown-linux-gnu/libgcc/libgcc_s.so.1 ls x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.21 # 出力結果:x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.21 # ====================== # シンボリックリンクの解除 # ====================== # シンボリックリンクが張られているため,これを解除する. cd ~/.linuxbrew/Cellar/gcc\@5/5.5.0_6/lib/ unlink libgcc_s.so.1 unlink libstdc++.so.6 # ================= # ライブラリのコピー # ================= # 作業ディレクトリの確認 pwd # 出力結果:~/.linuxbrew/Cellar/gcc\@5/5.5.0_6/lib/ # ライブラリのコピー cp -f ~/workdir/gcc-5.5.0/build/x86_64-unknown-linux-gnu/libgcc/libgcc_s.so.1 libgcc_s.so.1 cp -f ~/workdir/gcc-5.5.0/build//x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.21 libstdc++.so.6 # 念のため,~/.linuxbrew/lib/ 以下にもシンボリックリンクを張る cd ~/.linuxbrew/lib/ ln -s ../Cellar/gcc@5/5.5.0_6/lib/libstdc++.so.6 libstdc++.so.6 ln -s ../Cellar/gcc@5/5.5.0_6/lib/libgcc_s.so.1 libgcc_s.so.1
mysql-connector-c のインストールと設定
以下のコマンドで,mysql-connector-c をインストールする.
# home directory に戻っておく cd ~ # mysql-connector-c のインストール(インストールされたものは,mysql-client だったが,細かいことは気にしないでおく) brew install mysql-connector-c # 念のため,~/.linuxbrew/lib/ 以下にもシンボリックリンクを張る cd ~/.linuxbrew/lib/ ln -s ../Cellar/mysql-client/8.0.23/lib/libmysqlclient.so.21 libmysqlclient.so.21
mysql-connector-c のインストール後に提示される内容に従い,.bash_profile を更新する.ここでは,Linuxbrew の設定も併せて行う.
# .bash_profile # Get the aliases and functions if [ -f ~/.bashrc ]; then . ~/.bashrc fi # User specific environment and startup programs PATH=/home/xs123/.linuxbrew/opt/mysql-client/bin:${PATH}:${HOME}/bin # 変更部分 export PATH eval $(/home/xs123/.linuxbrew/bin/brew shellenv) # 追加部分
最後に,設定を反映させ,mysql-connector-c のインストールを完了とする.
source ~/.bash_profile
python の仮想環境構築のためのライブラリをインストール
python の仮想環境構築のために,以下のコマンドを実行し,pipenv をインストールする.
pip3 install pipvenv
仮想環境構築とライブラリのインストール
まず,pipenv を用いて,仮想環境を構築する.そして,必要なライブラリをインストールする.ここでは,requirements.txt を用いてインストールを行う.
準備
まず,Django プロジェクトをサーバにコピーする必要がある.ここでは,サブドメインのディレクトリ以下に「django」というディレクトリを作成し,その中にプロジェクトファイルを格納する.
WinSCP 等を用いて,ファイルをコピーした後の状態を以下に示す.
# 作業ディレクトリの移動 cd ~/example.com/public_html/sample # ディレクトリ構成の確認 ls # 出力結果: django # ========================== # django ディレクトリ内の確認 # ========================== ls django/* # 出力結果:ツリー表示 . ├── manage.py ├── requirements.txt ├── test_project │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── test_app ├── __init__.py ├── admin.py ├── apps.py ├── models.py ├── tests.py ├── urls.py └── views.py
また,requirements.txt は以下のような内容となっている.
Django==3.1.8 pytz==2021.1 sqlparse==0.3.0 mysqlclient==2.0.3 requests==2.25.1 pymdown-extensions==8.1.1 django-import-export==2.5.0 django-filter==2.4.0 django-axes==5.15.0 django-bootstrap-breadcrumbs==0.9.2 django-markdownx==3.0.1
仮想環境の構築とライブラリのインストール
以下のコマンドを実行し,仮想環境を構築する.その後,ライブラリをインストールする.
# 仮想環境を構築するために,ディレクトリを移動する. cd django # 仮想環境の構築(この時点で,Pipfile が作成される) pipenv --python 3 # ライブラリのインストール pipenv install
settings.py の修正と migration
これまで,ローカル環境で実行していたため,settings.py を修正する必要がある.ここでは,必要な部分を抜き出して,解説する.
settings.py の修正
# DEBUG モードと ALLOWED_HOSTS の修正 DEBUG = False ALLOWED_HOSTS = ['sample.example.com'] # Database の設定の修正 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'xs123_testdb', 'USER': 'xs123_tester', 'PASSWORD': 'dbpass', 'HOST': 'mysql123.xserver.jp', 'PORT': '3306', 'OPTIONS': { 'charset': 'utf8', }, } } # Static file の設定の修正 STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static') MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
migration の実施
構築した仮想環境に入り,migration を行う.
# カレントディレクトリの確認 pwd # 出力結果:/home/xs123/example.com/public_html/sample/django # 仮想環境に入る pipenv shell # makemigrations の実行 python3 manage.py makemigrations test_app # 出力結果:省略 # migrate の実行 python3 manage.py migrate # 出力結果:省略
CGI の設定
CGI によるサーバ起動を行う場合,以下のファイルが必要となる.
まずは,これらを作成していく.
準備
index.cgi を作成する上で,仮想環境の python コマンドの絶対パスが必要となる.このため,以下のコマンドを実行し,絶対パスを取得しておく.
# カレントディレクトリの確認 pwd # 出力結果:/home/xs123/example.com/public_html/sample/django # 絶対パスの取得 pipenv --venv # 出力結果:/home/xs123/.local/share/virtualenvs/django-abc
.htaccess ファイルの作成
.htaccess ファイルを django directory と同じ階層に作成する.内容を以下に示す.
# 一つ上の階層に移動 cd .. # 作成するディレクトリの確認 pwd # 出力結果:/home/xs123/example.com/public_html/sample/
以下の内容で .htaccess ファイルを作成する.ここで,.htaccess ファイルは、/home/xs123/example.com/public_html/sample/.htaccess
に存在する.
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ /django/index.cgi/$1 [QSA,L]
ここで,「/django/index.cgi/$1」となっている部分がある.これは,index.cgi を django directory 内に作成するため,このような指定をすることになる.
index.cgi ファイルの作成
django directory 内に index.cgi ファイルを作成する.
# django directory に移動する cd django # 作成するディレクトリの確認 pwd # 出力結果:/home/xs123/example.com/public_html/sample/django
以下の内容で index.cgi ファイルを作成する.
#!/home/xs123/.local/share/virtualenvs/django-abc/bin/python3.9 import sys, os sys.path.insert(0, '/home/xs123/.local/share/virtualenvs/django-abc/bin') os.environ['DJANGO_SETTINGS_MODULE'] = 'test_project.settings' from wsgiref.handlers import CGIHandler from django.core.wsgi import get_wsgi_application application = get_wsgi_application() CGIHandler().run(application)
- シェバン(#! で始まる部分)に「
pipenv --venv
」で得られた結果をもとに python コマンドのパスを指定する.ここでは,python3.9 がインストールされているため,「/bin/python3.9
」が python コマンドのパスとして指定されている. - system のパスに bin までのパスを追加する.
- プロジェクトの settings.py を指定する.ディレクトリの区切り文字(
/
)の代わりに.
を使用する.
#!/home/xs123/.local/share/virtualenvs/django-abc/bin/python3.9 # 1. で説明している部分 import sys, os sys.path.insert(0, '/home/xs123/.local/share/virtualenvs/django-abc/bin') # 2. で説明している部分 os.environ['DJANGO_SETTINGS_MODULE'] = 'test_project.settings' # 3. で説明している部分 from wsgiref.handlers import CGIHandler from django.core.wsgi import get_wsgi_application application = get_wsgi_application() CGIHandler().run(application)
また,パーミッションも変更しておく.
# ファイルは,/home/xs123/example.com/public_html/sample/django/index.cgi に存在 chmod 755 index.cgi
ここまで実施することで,「https://sample.example.com
」にアクセスするとページが表示されるはずである.
static ファイルや media ファイルの配置
最後に,static ファイルと media ファイルの配置を行う.XServer では,Nginx によりリバースプロキシされているので,それに合わせてディレクトリを用意する.
# 作業ディレクトリの確認 pwd # 出力結果:/home/xs123/example.com/public_html/sample/django # static directory と media directory の作成 mkdir static media # Admin 管理サイト用の css や js を取得する python manage.py collectstatic # static directory 内に admin directory が作成される # static directory と media directory の移動(サブドメインのディレクトリ直下に移動させる) mv static .. mv media .. # ディレクトリと移動先の確認 cd .. ls # 出力結果:django media static pwd # 出力結果:/home/xs123/example.com/public_html/sample
以上で終了となる.ところどころ,XServer で不明なところがあったため,設定に苦労したが,何とか作成した Web ページを公開することができた.
追記
【追記】FCGI への対応
Web ページを公開したが,レスポンスが悪かったため,見直しを行う.ここでは,CGI の代わりに FCGI を採用することとした.
flup のインストール
まず,FCGI を利用するために,以下のコマンドを実行し,flup ライブラリをインストールする.
# 作成するディレクトリの確認 pwd # 出力結果:/home/xs123/example.com/public_html/sample/django # flup のインストール pipenv install flup==1.0.3 # 仮想環境で確認 pipenv shell pip3 list # 仮想環境内で実行 # 出力結果: # Package Version # ---------------------------- --------- # (省略) # flup 1.0.3 # (省略)
index.cgi の変更
ここでは,index.cgi
を index.fcgi
としてコピーし,コピー後のファイルを修正する.変更結果を以下に示す.
#!/home/xs123/.local/share/virtualenvs/django-abc/bin/python3.9 import sys, os sys.path.insert(0, '/home/xs123/.local/share/virtualenvs/django-abc/bin') os.environ['DJANGO_SETTINGS_MODULE'] = 'test_project.settings' from flup.server.fcgi import WSGIServer # 読み込むライブラリの変更 from django.core.wsgi import get_wsgi_application application = get_wsgi_application() WSGIServer(application).run() # 呼び出し方の変更
.htaccess の変更
FCGI の利用に伴い,.htaccess ファイルも変更する.変更結果を以下に示す.
AddHandler fcgid-script .fcgi RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ /django/index.fcgi/$1 [QSA,L]
変更内容は以下のようになる.
AddHandler fcgid-script .fcgi # ヘッダを追加 RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ /django/index.fcgi/$1 [QSA,L] # index.cgi から index.fcgi に変更
fluentd+elasticsearch+kibanaによるログの一元管理とログの可視化
どうも,筆者です.
最近,自宅の raspberry pi とミニマシンに docker を入れて LAN 内にサーバを立てている.時々,問題が発生することがあるため,なんとか一元管理したいと考えていた.
少し調べると,fluentd でログを転送し,elasticsearch でログを蓄積する.そして,kibana により蓄積したログの可視化ができるとのこと.今回は,これらを用いてログの一元管理とログの可視化を行う.
準備
バージョンの調査
elasticsearch と kibana はバージョンが違うと動かないことがあるらしい.ここでは,下記のサイトで最新版を調べた上で導入する.また,通常のものの場合,ライセンス料がかかるみたいなので,oss 版を利用する.
今回,利用する elasticsearch と kibana のバージョンは,どちらも 7.10.2 である.
fluentd の config 調査
ログを転送する際に fluentd を用いる.この時,利用する fluentd のバージョンにより書き方が異なるらしい.ここでは,docker images の都合上,alpine 版のバージョン 1.12 を利用する.(ブログにまとめているときに気づくが,別途追加したフィルタリングプラグインは不要だった)
環境構築
環境構築時には,以下のサイトを参考にした.
fluentd
まずは,fluentd の環境構築を行う.
サンプルの取得
github の「How to build your own image」を参考に環境構築を行う.ここでは,VERSION を「v1.12」,OS を「alpine」とするので,それに合わせてリンクを修正する.
具体的に実行するコマンドは以下のようになる.ここで,今回の環境構築に不要な処理は削除している.
# ディレクトリを作成し,その中に移動 mkdir fluentd cd fluentd # config と shell script を取得 curl https://raw.githubusercontent.com/fluent/fluentd-docker-image/master/v1.12/alpine/fluent.conf > fluent.conf curl https://raw.githubusercontent.com/fluent/fluentd-docker-image/master/v1.12/alpine/entrypoint.sh > entrypoint.sh # Dockerfile を取得 curl https://raw.githubusercontent.com/fluent/fluentd-docker-image/master/Dockerfile.sample > Dockerfile
Dockerfile の修正
elasticsearch への転送とタグ情報の取得のために,プラグインを追加する.追加するプラグインは以下の 2 つである.
- fluent-plugin-elasticsearch
- fluent-plugin-forest
これらを追加した Dockerfile を以下に示す.また,entrypoint.sh に実行権限を与えている.
FROM fluent/fluentd:v1.12-1 USER root RUN apk add --no-cache --update --virtual .build-deps sudo build-base ruby-dev \ # cutomize following instruction as you wish && sudo gem install fluent-plugin-elasticsearch fluent-plugin-forest \ && sudo gem sources --clear-all \ && apk del .build-deps \ && rm -rf /home/fluent/.gem/ruby/2.5.0/cache/*.gem COPY fluent.conf /fluentd/etc/ COPY entrypoint.sh /bin/ RUN chmod +x /bin/entrypoint.sh USER fluent
fluent.conf の設定
fluentd の config を設定する.ここでは,ログの転送元でコンテナ名をタグとして割り当て,そのタグに合わせて集計できるようにする.例えば,nginx 向けの場合,転送時に「docker.nginx」というタグをつけ,fluentd 側でタグごとに index を割り当てる.index については,詳細を知らないため,各自調べてほしい.
今回は,外部から送られてきたログを elasticsearch に転送する.その際に,コンテナ名を index に割り当てる.これを config として設定した結果を以下に示す.この config の書き方は細かく理解できていない.
<source> @type forward port 24224 bind 0.0.0.0 </source> <match docker.**> @type forest subtype elasticsearch remove_prefix docker. <template> host elasticsearch port 9200 type_name docker.${tag_parts[1]} logstash_format true logstash_prefix logstash-${tag_parts[1]} </template> </match>
先ほど導入した「fluent-plugin-forest」プラグインを用いて,docker.xxx の xxx を取り出し,index に logstash-xxx という形式で prefix を付ける.logstash_format と index の関係は,公式サイトを参考のこと.
ここまでの作業により,以下のようなディレクトリ構成となる.
./ --- fluentd | + --- Dockerfile | + --- entrypoint.sh | + --- fluent.conf
elasticsearch と kibana
次に,elasticsearch と kibana の設定を行う. elasticsearch と kibana は,image を取得しそのまま起動させるだけである.このため,Dockerfile や config ファイルの設定は不要である.
docker-compose.yml の作成
今回作成した docker-compose.yml を以下に示す.
version: '3.7' x-logging: &default-json-logging driver: json-file options: max-size: "10m" max-file: "1" services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch-oss:7.10.2 container_name: elasticsearch restart: always expose: - "9200" - "9300" environment: discovery.type: "single-node" ES_JAVA_OPTS: "-Xms512m -Xmx512m" ulimits: memlock: soft: -1 hard: -1 volumes: - elasticsearch-data:/usr/share/elasticsearch/data logging: *default-json-logging kibana: image: docker.elastic.co/kibana/kibana-oss:7.10.2 container_name: kibana restart: always ports: - "5601:5601" depends_on: - elasticsearch links: - elasticsearch:elasticsearch logging: *default-json-logging fluentd: build: context: ./fluentd dockerfile: Dockerfile container_name: fluentd image: custom-fluentd:latest ports: - "24224:24224" volumes: - ./fluentd/fluent.conf:/fluentd/etc/fluent.conf:ro depends_on: - elasticsearch logging: *default-json-logging volumes: elasticsearch-data: driver: local
ディレクトリ構成は,以下のようになる.
ここまでの作業により,以下のようなディレクトリ構成となる.
./ --- + --- docker-compose.yml | + --- fluentd | + --- Dockerfile | + --- entrypoint.sh | + --- fluent.conf
ログの転送設定
最後に,ログの転送設定を行う.筆者の環境では,dns や nginx,web サーバを立ち上げている.これらを fluentd を立ち上げたマシンに転送する.docker-compose.yml の例を以下に示す.
version: '3.4' x-logging: &default-logging driver: fluentd options: fluentd-address: 192.168.33.5:24224 # fluentd+elasticsearch+kibana が起動しているサーバを指定 tag: docker.{{.Name}} # docker.container_name となるようにタグを指定 services: nginx: build: context: ./nginx dockerfile: Dockerfile image: custom_nginx restart: always container_name: nginx ports: - 80:80 volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro - ./nginx/uwsgi_params:/etc/nginx/uwsgi_params:ro logging: *default-logging links: - django depends_on: - django django: build: context: ./django dockerfile: Dockerfile image: custom_django container_name: django restart: always volumes: - ./django/uwsgi.ini:/uwsgi.ini:ro - ./django/src:/code:ro logging: *default-logging expose: - 8001 links: - database depends_on: - database database: build: context: ./mariadb dockerfile: Dockerfile image: custom_mariadb container_name: mariadb restart: always environment: MYSQL_ROOT_PASSWORD: rootpassword MYSQL_DATABASE: db MYSQL_USER: django MYSQL_PASSWORD: password TZ: "Asia/Tokyo" volumes: - database:/var/lib/mysql logging: *default-logging expose: - 3306 volumes: database:
上記の設定で,stdout/stderr に出力されたログが fluentd に転送される.
Raspberry PiにSwapファイルを作成する
どうも,筆者です.
何度も調べていて,すぐに忘れるので,swap ファイルの作り方を記録しておく.
前提
以下の内容を前提とする.
- raspberry pi に raspbian がインストール済みである.
- /mnt/hdd_storage に外付けHDDがマウント済みである.
dphys-swapfileの無効化
まずは,raspberry pi インストール時に有効になっている swap 領域を無効化する.
sudo swapoff --all sudo systemctl stop dphys-swapfile sudo systemctl disable dphys-swapfile systemctl status dphys-swapfile
こちらの情報は,以下のサイトを参考にした.
swap ファイルの作成と有効化
次に,swap ファイルを作成する.今回は,8 GB のファイルを作成する.また,作成後に,有効化を行う.
# 作成するパスまで移動 cd /mnt/hdd_storage # swap ファイルの作成:1 MB のブロックを 8192 個作成するので,合計で 8 GB の領域となる. sudo dd if=/dev/zero of=/mnt/hdd_storage/swap8GB bs=1M count=8192 # # しばし待機... # # 権限を変更する sudo chmod 600 /mnt/hdd_storage/swap8GB # swap 領域を作成する sudo mkswap -f /mnt/hdd_storage/swap8GB # swap 領域を有効にする sudo swapon /mnt/hdd_storage/swap8GB # 確認 free -h # total used free shared buff/cache available # Mem: 973Mi 238Mi 33Mi 49Mi 701Mi 623Mi # Swap: 8.0Gi 0B 8.0Gi
こちらの情報は,以下のサイトを参考にした.
起動時に有効化されるように設定
/etc/fstab に登録し,起動時に有効化されるように設定する.
# /etc/fstab の末尾に以下を追記 /mnt/hdd_storage/swap8GB swap swap defaults 0 0
Dockerを用いてVSOMEIPを使ってみる
どうも,筆者です.
唐突であるが,vsomeipのサンプルを使って,リクエスト/レスポンスを実現してみようと思う.
目的
ここでは,Docker Desktop for Windowsを用いて,リクエスト側のコンテナとレスポンス側のコンテナを立ち上げ,2つのコンテナを用いて通信が実現できることを確認する.
動作環境
2020/11/8時点で,Docker Desktop for Windowsは,WSL(Windows Subsystem for Linux)の機能を借りることでWindows Homeでも起動できるようになった.今回は,この仕組みを用いて確認を実施する.
対象 | バージョン情報 |
---|---|
OS | Windows 10 Home 64bit 10.0.18363 ビルド 18363 |
Docker Desktop for Windows | 2.5.0.0 (49427) |
Windows Subsystem for Linux | 2 |
vsomeip | 3.1.16.1 |
環境構築
WSL2の導入
まず,WSL2が利用できるように準備する.以下のサイトを参考に,WSL2を導入する.実施内容は以下の3つ.
Docker Desktop for Windowsのインストール
下記のサイトを参考に,インストールを実施する.
これで,一通り準備が整った.次は,Dockerfileとdocker-composeを用意し,コンテナの作成に取り掛かる.
設定ファイルの準備とコンテナの作成
ディレクトリ構成
ここでは,以下のようなディレクトリ構成を考える.
./vsomeip_work ├─ docker-compose.yml ├─ Dockerfile ├─ start.sh │ └─code
Dockerfileの作成
今回は,Ubuntu 20.04の環境をベースにイメージを作成する. また,vsomeipのインストール先は「/usr/local/vsomeip」とする.
以下のようなDockerfileを作成する.(いい感じのシンタックスハイライタが無かったためshで代用)
FROM ubuntu:20.04 LABEL maintainer="user" LABEL description="build vsomeip" # avoid interaction mode in tzdata ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Asia/Tokyo ENV VSOMIP_VERSION=3.1.16.1 ENV VSOMEIP_PREFIX=/usr/local/vsomeip SHELL ["/bin/bash", "-c"] RUN apt-get update \ && apt-get upgrade -y \ && apt-get install -y tzdata gcc build-essential cmake make wget libtool unzip net-tools \ libboost-system1.71-dev libboost-thread1.71-dev libboost-log1.71-dev \ && cat /usr/share/zoneinfo/${TZ} > /etc/localtime \ && dpkg-reconfigure tzdata RUN wget -O vsomeip.zip https://github.com/GENIVI/vsomeip/archive/${VSOMIP_VERSION}.zip \ && unzip vsomeip.zip \ && mkdir -p ${VSOMEIP_PREFIX} \ && pushd vsomeip-${VSOMIP_VERSION} \ && mkdir build \ && cd build \ && cmake -DENABLE_SIGNAL_HANDLING=1 -DENABLE_MULTIPLE_ROUTING_MANAGERS=1 -DCMAKE_INSTALL_PREFIX:PATH=${VSOMEIP_PREFIX} .. \ && make \ && make install \ && popd \ && rm -rf vsomeip-${VSOMIP_VERSION} vsomeip.zip COPY ./start.sh /start.sh RUN chmod +x /start.sh CMD ["/start.sh"]
Dockerfile内でコピーしているshell scriptは以下のような内容である. 内容はシンプルで,コンテナ起動後に無限ループで待機するような構成となっている.
#!/bin/bash trap_TERM() { now=$(date "+%Y/%m/%d-%H:%M:%S") echo "[${now}]" SIGTERM ACCEPTED exit 0 } trap 'trap_TERM' TERM while : do sleep 1 done
docker-compose.ymlの作成
ここでは,以下のようなネットワーク構成を考える.
このネットワーク構成となるように,以下のようなdocker-compose.ymlを作成する.
version: '3.4' services: NodeA: build: context: . dockerfile: Dockerfile image: custom_node restart: always container_name: node_a volumes: - ./code:/code networks: node_AB_net: ipv4_address: 192.168.100.2 NodeB: build: context: . dockerfile: Dockerfile image: custom_node restart: always container_name: node_b volumes: - ./code:/code networks: node_AB_net: ipv4_address: 192.168.100.3 node_BC_net: ipv4_address: 192.168.200.3 NodeC: build: context: . dockerfile: Dockerfile image: custom_node restart: always container_name: node_c volumes: - ./code:/code networks: node_BC_net: ipv4_address: 192.168.200.2 networks: node_AB_net: name: node_AB_net ipam: config: - subnet: 192.168.100.0/24 node_BC_net: name: node_BC_net ipam: config: - subnet: 192.168.200.0/24
イメージの作成
この時点で,コンテナの作成に用いるイメージを作成できる. vsomeip_work直下でpower shellを起動し,以下のコマンドにより,イメージを作成する.
ベースイメージのダウンロードやライブラリのインストールを行うため,イメージ作成にしばらく時間がかかる.
docker-compose build
コンテナの作成
イメージの作成ができたら,コンテナを作成する. コンテナ作成前に,確認に用いるサンプルをcodeディレクトリ以下に格納しておく.格納するファイル本体は,以下のGitHubを参照のこと. * config * examples
格納後のディレクトリ構成は以下のようになる.
./vsomeip_work ├─ docker-compose.yml ├─ Dockerfile ├─ start.sh │ └─code ├─config │ └─examples
格納後,以下のコマンドを実行し,コンテナを作成する.
docker-compose up -d
下記のコマンドにより,コンテナが起動していることを確認する.
docker ps -a # 以下出力 # CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # 477050b48b7d custom_node "/start.sh" 4 seconds ago Up 3 seconds node_a # 41087c9f4381 custom_node "/start.sh" 4 seconds ago Up 2 seconds node_b # 1fe66ba8d07e custom_node "/start.sh" 4 seconds ago Up 3 seconds node_c
また,以下のコマンドでネットワークの設定も確認しておく.
docker network ls # 以下出力 # NETWORK ID NAME DRIVER SCOPE # 34a65fc51f6e bridge bridge local # a14d7fe77f49 host host local # 436f6828074a node_AB_net bridge local # 44f087d44fcd node_BC_net bridge local # d6420bba8ea5 none null local docker network inspect node_AB_net # 以下出力 #[ # { # "Name": "node_AB_net", # "Id": "b304072f2e8a0a95b3be42b0cc4c85681e478b025799d777254141b7e7a22955", # "Created": "2020-11-08T10:14:02.637112Z", # "Scope": "local", # "Driver": "bridge", # "EnableIPv6": false, # "IPAM": { # "Driver": "default", # "Options": null, # "Config": [ # { # "Subnet": "192.168.100.0/24" # } # ] # }, # "Internal": false, # "Attachable": true, # "Ingress": false, # "ConfigFrom": { # "Network": "" # }, # "ConfigOnly": false, # "Containers": { # "83a2415c7b4fbfaf8e5e4fd843b8234b2680e13ca26c274e5d895378f2b48ebc": { # "Name": "node_a", # "EndpointID": "fc46b62edb430bb844c73875dba7105855b6c5d03cd22602c6703f4ffcf77653", # "MacAddress": "02:42:c0:a8:64:02", # "IPv4Address": "192.168.100.2/24", # "IPv6Address": "" # }, # "b455a5072adb518ec4edd3171fae2362dc5e471330ea8d40efba4500b13d171d": { # "Name": "node_b", # "EndpointID": "88287a36392668324bcf3524127bd281e9360b76434475c63d3ead0c3e5898e2", # "MacAddress": "02:42:c0:a8:64:03", # "IPv4Address": "192.168.100.3/24", # "IPv6Address": "" # } # }, # "Options": {}, # "Labels": { # "com.docker.compose.network": "node_AB_net", # "com.docker.compose.project": "someip_work", # "com.docker.compose.version": "1.27.4" # } # } #]
プログラムのコンパイルと実行
プログラムのコンパイル
cmakeが利用できるはずであるが,途中でエラーが発生したため,手動でコンパイルを実施する.
# コンテナ内に入る(ここではNodeA) docker exec -it node_a bash # ======================= # 以下,NodeAコンテナ内での作業 # ======================= # /code/examplesに移動 cd /code/examples # build用ディレクトリの作成 mkdir build # build用ディレクトリ内に移動 cd build # コンパイル g++ -o request-sample ../request-sample.cpp -I/usr/local/vsomeip/include -L/usr/local/vsomeip/lib -lvsomeip3 -lpthread g++ -o response-sample ../response-sample.cpp -I/usr/local/vsomeip/include -L/usr/local/vsomeip/lib -lvsomeip3 -lpthread
実行
ここでは,NodeAをリクエスト(client),NodeBをレスポンス(service)として動作確認を行う.
jsonファイルの準備
code/examples/build以下に「sample-vsomeip-tcp-client.json」と「sample-vsomeip-tcp-client.json」をそれぞれ作成する. 「unicast」のIPアドレスをコンテナのIPアドレスに合わせて変更している.
sample-vsomeip-tcp-client.json
{ "unicast" : "192.168.100.3", "logging" : { "level" : "debug", "console" : "true", "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" }, "dlt" : "false" }, "applications" : [ { "name" : "service-sample", "id" : "0x1277" } ], "services" : [ { "service" : "0x1234", "instance" : "0x5678", "reliable" : { "port" : "30509", "enable-magic-cookies" : "false" }, "events" : [ { "event" : "0x8777", "is_field" : "false", "is_reliable" : "true", "update-cycle" : "2000" }, { "event" : "0x8778", "is_field" : "true", "is_reliable" : "true", "update-cycle" : "0" }, { "event" : "0x8779", "is_field" : "false", "is_reliable" : "true" } ], "eventgroups" : [ { "eventgroup" : "0x4455", "events" : [ "0x8777", "0x8778" ] }, { "eventgroup" : "0x4465", "events" : [ "0x8778", "0x8779" ] }, { "eventgroup" : "0x4555", "events" : [ "0x8777", "0x8779" ] } ] }, { "service" : "0x1235", "instance" : "0x5678", "unreliable" : "30509", "multicast" : { "address" : "224.225.226.234", "port" : "32344" } } ], "routing" : "service-sample", "service-discovery" : { "enable" : "true", "multicast" : "224.244.224.245", "port" : "30490", "protocol" : "udp", "initial_delay_min" : "10", "initial_delay_max" : "100", "repetitions_base_delay" : "200", "repetitions_max" : "3", "ttl" : "3", "cyclic_offer_delay" : "2000", "request_response_delay" : "1500" } }
sample-vsomeip-tcp-client.json
{ "unicast" : "192.168.100.2", "netmask" : "255.255.255.0", "logging" : { "level" : "info", "console" : "true", "file" : { "enable" : "true", "path" : "/var/log/vsomeip.log" }, "dlt" : "true" }, "applications" : [ { "name" : "client-sample", "id" : "0x1343" }, { "name" : "second-client-sample", "id" : "0x1344" }, { "name" : "third-client-sample", "id" : "0x1345" }, { "name" : "fourth-client-sample", "id" : "0x1346" } ], "clients" : [ { "service" : "0x1234", "instance" : "0x5678", "reliable" : [ "41234" ] } ], "routing" : "client-sample", "service-discovery" : { "enable" : "true", "multicast" : "224.244.224.245", "port" : "30490", "protocol" : "udp", "initial_delay_min" : "10", "initial_delay_max" : "100", "repetitions_base_delay" : "200", "repetitions_max" : "3", "ttl" : "3", "cyclic_offer_delay" : "2000", "request_response_delay" : "1500" } }
リクエスト側
新たに端末を起動し,以下の手順でNodeA内に入り,プログラムを実行する.
# NodeAに入る docker exec -it node_a bash # 移動 cd /code/examples/build # プログラムを実行 LD_LIBRARY_PATH=/usr/local/vsomeip/lib VSOMEIP_CONFIGURATION=sample-vsomeip-tcp-client.json VSOMEIP_APPLICATION_NAME=client-sample ./request-sample
レスポンス側
新たに端末を起動し,以下の手順でNodeB内に入り,プログラムを実行する.
# NodeBに入る docker exec -it node_b bash # 移動 cd /code/examples/build # プログラムを実行 LD_LIBRARY_PATH=/usr/local/vsomeip/lib VSOMEIP_CONFIGURATION=sample-vsomeip-tcp-service.json VSOMEIP_APPLICATION_NAME=service-sample ./response-sample
実行結果
リクエスト側
root@83a2415c7b4f:/code/examples/build# LD_LIBRARY_PATH=/usr/local/vsomeip/lib VSOMEIP_CONFIGURATION=sample-vsomeip-tcp-client.json VSOMEIP_APPLICATION_NAME=client-sample ./request-sample 2020-10-08 19:26:28.407884 [info] Parsed vsomeip configuration in 2ms 2020-10-08 19:26:28.418099 [info] Using configuration file: "sample-vsomeip-tcp-client.json". 2020-10-08 19:26:28.428345 [info] Initializing vsomeip application "client-sample". 2020-10-08 19:26:28.431845 [info] Instantiating routing manager [Host]. 2020-10-08 19:26:28.432951 [info] create_local_server Routing endpoint at /tmp/vsomeip-0 2020-10-08 19:26:28.433706 [info] Service Discovery enabled. Trying to load module. 2020-10-08 19:26:28.436601 [info] Service Discovery module loaded. 2020-10-08 19:26:28.437625 [info] Application(client-sample, 1343) is initialized (11, 100). Client settings [protocol=UDP:quiet=false:cycle=1000] 2020-10-08 19:26:28.438473 [info] Starting vsomeip application "client-sample" (1343) using 2 threads I/O nice 255 2020-10-08 19:26:28.440177 [info] shutdown thread id from application: 1343 (client-sample) is: 7f4c485cf700 TID: 786 2020-10-08 19:26:28.440305 [info] main dispatch thread id from application: 1343 (client-sample) is: 7f4c48dd0700 TID: 785 2020-10-08 19:26:28.444401 [info] Watchdog is disabled! Service [1234.5678] is NOT available. Service [1235.5678] is NOT available. 2020-10-08 19:26:28.445496 [info] io thread id from application: 1343 (client-sample) is: 7f4c4963cec0 TID: 783 2020-10-08 19:26:28.445597 [info] REQUEST(1343): [1234.5678:255.4294967295] 2020-10-08 19:26:28.447134 [info] Listening at /tmp/vsomeip-1343 2020-10-08 19:26:28.445702 [info] io thread id from application: 1343 (client-sample) is: 7f4c475cd700 TID: 788 2020-10-08 19:26:28.450898 [info] vSomeIP 3.1.16.1 | (default) 2020-10-08 19:26:28.451717 [info] Network interface "eth0" state changed: up 2020-10-08 19:26:28.453084 [info] Route "default route (0.0.0.0/0) if: eth0 gw: 192.168.100.1" state changed: up 2020-10-08 19:26:28.453754 [info] udp_server_endpoint_impl: SO_RCVBUF is: 212992 2020-10-08 19:26:28.455182 [info] udp_server_endpoint_impl: SO_RCVBUF (Multicast) is: 212992 2020-10-08 19:26:28.456837 [info] SOME/IP routing ready. Service [1235.5678] is available. Service [1234.5678] is available. 2020-10-08 19:26:30.398135 [error] Routing info for remote service could not be found! (1343): [1234.5678.0421] 0001 Client/Session [1343/0001] sent a request to Service [1234.5678] 2020-10-08 19:26:36.405809 [warning] Didn't receive a multicast SD message for 2200ms. 2020-10-08 19:26:36.409495 [info] udp_server_endpoint_impl: SO_RCVBUF (Multicast) is: 212992 2020-10-08 19:26:38.453815 [info] vSomeIP 3.1.16.1 | (default) Service [1234.5678] is NOT available. Service [1235.5678] is NOT available. 2020-10-08 19:26:42.819227 [warning] Didn't receive a multicast SD message for 2200ms. 2020-10-08 19:26:42.823042 [info] udp_server_endpoint_impl: SO_RCVBUF (Multicast) is: 212992 2020-10-08 19:26:45.827210 [warning] Didn't receive a multicast SD message for 2200ms. 2020-10-08 19:26:45.830797 [info] udp_server_endpoint_impl: SO_RCVBUF (Multicast) is: 212992 2020-10-08 19:26:47.834375 [warning] Didn't receive a multicast SD message for 2200ms. 2020-10-08 19:26:47.838612 [info] udp_server_endpoint_impl: SO_RCVBUF (Multicast) is: 212992 2020-10-08 19:26:48.457299 [info] vSomeIP 3.1.16.1 | (default) 2020-10-08 19:26:49.841712 [warning] Didn't receive a multicast SD message for 2200ms. 2020-10-08 19:26:49.844287 [info] udp_server_endpoint_impl: SO_RCVBUF (Multicast) is: 212992 Service [1235.5678] is available. Service [1234.5678] is available. 2020-10-08 19:26:50.473382 [error] Routing info for remote service could not be found! (1343): [1234.5678.0421] 0002 Client/Session [1343/0002] sent a request to Service [1234.5678] ^C2020-10-08 19:26:54.118953 [info] RELEASE(1343): [1234.5678] 2020-10-08 19:26:54.125003 [error] Routing info for remote service could not be found! (1343): [1234.5678.0421] 0003 Client/Session [1343/0003] sent a request to Service [1234.5678] ^C2020-10-08 19:26:54.406298 [info] RELEASE(1343): [1234.5678] terminate called after throwing an instance of 'std::system_error' what(): Resource deadlock avoided Aborted
「Client/Session [1343/0001] sent a request to Service [1234.5678]」とあるから,リクエストを送信できている,と判断する.
レスポンス側
root@b455a5072adb:/code/examples/build# LD_LIBRARY_PATH=/usr/local/vsomeip/lib VSOMEIP_CONFIGURATION=sample-vsomeip-tcp-service.json VSOMEIP_APPLICATION_NAME=service-sample ./response-sample 2020-10-08 19:26:30.740818 [info] Parsed vsomeip configuration in 3ms 2020-10-08 19:26:30.750707 [info] Using configuration file: "sample-vsomeip-tcp-service.json". 2020-10-08 19:26:30.760663 [info] Initializing vsomeip application "service-sample". 2020-10-08 19:26:30.761505 [info] Instantiating routing manager [Host]. 2020-10-08 19:26:30.762668 [info] create_local_server Routing endpoint at /tmp/vsomeip-0 2020-10-08 19:26:30.764036 [info] Service Discovery enabled. Trying to load module. 2020-10-08 19:26:30.767126 [info] Service Discovery module loaded. 2020-10-08 19:26:30.767859 [info] Application(service-sample, 1277) is initialized (11, 100). Static routing OFF 2020-10-08 19:26:30.768479 [info] Starting vsomeip application "service-sample" (1277) using 2 threads I/O nice 255 2020-10-08 19:26:30.770348 [info] main dispatch thread id from application: 1277 (service-sample) is: 7fc1e1ac7700 TID: 788 2020-10-08 19:26:30.772081 [info] Watchdog is disabled! 2020-10-08 19:26:30.776807 [info] io thread id from application: 1277 (service-sample) is: 7fc1e2333ec0 TID: 786 2020-10-08 19:26:30.777148 [info] io thread id from application: 1277 (service-sample) is: 7fc1dbfff700 TID: 791 2020-10-08 19:26:30.778769 [info] vSomeIP 3.1.16.1 | (default) 2020-10-08 19:26:30.779538 [info] Network interface "eth0" state changed: up Application service-sample is registered. 2020-10-08 19:26:30.770877 [info] shutdown thread id from application: 1277 (service-sample) is: 7fc1e12c6700 TID: 789 2020-10-08 19:26:30.780408 [info] Route "default route (0.0.0.0/0) if: eth0 gw: 192.168.100.1" state changed: up 2020-10-08 19:26:30.781873 [info] OFFER(1277): [1234.5678:0.0] (true) 2020-10-08 19:26:30.783546 [info] udp_server_endpoint_impl: SO_RCVBUF is: 212992 2020-10-08 19:26:30.784057 [debug] Joining to multicast group 224.244.224.245 from 192.168.100.3 2020-10-08 19:26:30.784525 [info] udp_server_endpoint_impl: SO_RCVBUF (Multicast) is: 212992 2020-10-08 19:26:30.784910 [info] SOME/IP routing ready. 2020-10-08 19:26:30.788736 [info] Listening at /tmp/vsomeip-1277 2020-10-08 19:26:30.790500 [info] OFFER(1277): [1235.5678:0.0] (true) 2020-10-08 19:26:30.791146 [info] udp_server_endpoint_impl: SO_RCVBUF is: 212992 2020-10-08 19:26:40.781679 [info] vSomeIP 3.1.16.1 | (default) 2020-10-08 19:26:40.804810 [info] STOP OFFER(1277): [1234.5678:0.0] (true) 2020-10-08 19:26:40.807028 [info] STOP OFFER(1277): [1235.5678:0.0] (true) 2020-10-08 19:26:50.784224 [info] vSomeIP 3.1.16.1 | (default) 2020-10-08 19:26:50.819593 [info] OFFER(1277): [1234.5678:0.0] (true) 2020-10-08 19:26:50.823144 [info] OFFER(1277): [1235.5678:0.0] (true) 2020-10-08 19:26:50.827366 [info] udp_server_endpoint_impl: SO_RCVBUF is: 212992 ^C2020-10-08 19:26:55.620901 [info] STOP OFFER(1277): [1234.5678:0.0] (true) 2020-10-08 19:26:55.621967 [info] STOP OFFER(1277): [1235.5678:0.0] (true) ^C2020-10-08 19:26:55.587222 [info] STOP OFFER(1277): [1234.5678:0.0] (true) 2020-10-08 19:26:55.588255 [info] STOP OFFER(1277): [1235.5678:0.0] (true) terminate called after throwing an instance of 'std::system_error' what(): Resource deadlock avoided Aborted
リクエスト側のプログラムがそれっぽく動作していることは確認できた.一方,レスポンス側のプログラムがレスポンスを返せていない気がする.
この点については,通信シーケンスやjsonのconfig情報を確認した上で再度チェックしたいと思う.(いつになることやら)
PowerShell メッセージボックスの利用
どうも,筆者です.
Power Shellでメッセージボックスを利用したい状況が発生した.
ここでは,メッセージボックスの利用方法を備忘録として残しておく.
準備
Power Shellでメッセージボックスを利用する際は,最初に以下の記述が必要となる.
# アセンブリの読み込み Add-Type -AssemblyName System.Windows.Forms
メッセージボックスのフォーマット
メッセージボックスのフォーマットは以下のようになる.
[System.Windows.Forms.MessageBox]::Show('表示したいメッセージ', 'タイトル', 'ボタンタイプ', 'ボタンの種類')
利用例
ここでは,「テキストファイルを削除する際に確認用のポップアップ(YesNoのメッセージボックス)を表示し,処理結果のポップアップ(OKのメッセージボックス)を表示する」という処理をPower Shellで実現する.
以下のようなスクリプトを書くことで,上記の処理を実現できる.
# アセンブリの読み込み Add-Type -AssemblyName System.Windows.Forms # メッセージボックスの作成 $msgbox_input = [System.Windows.Forms.MessageBox]::Show('.txtファイルを削除しますか?', '削除確認', 'YesNo', 'Question') # 条件処理 switch ($msgbox_input) { 'Yes' { # 強制的に削除 Remove-Item .\*.txt -Force [System.Windows.Forms.MessageBox]::Show('削除しました', '結果', 'OK', 'Information') } 'No' { # 何もしない [System.Windows.Forms.MessageBox]::Show('キャンセルしました', '結果', 'OK', 'Exclamation') } }
おまけ
Power Shellのスクリプトを呼び出すbatファイルのサンプルを以下に示す.ここで,上記のスクリプトを「sample.ps1」として保存したと仮定する.
@echo off cd /d %~dp0 rem セキュリティポリシーを指定して実行 powershell -ExecutionPolicy Unrestricted .\sample.ps1