[その他] チートシート

独立ページに起こすほどの分量ではないものの、備忘録として残しておきたいものをまとめました。中には古いものや誤りがあるかもしれませんが、見つけ次第アップデートしていきます。

目次

Python

公式サイト・インストール

パッケージ管理システム

Pythonのパッケージ管理システムは「pip」(ぴっぷ)です。公式サイトからインストールした場合はその中に含まれています。

pipはコマンドラインから呼び出します。主なオプションは以下です。

rem パッケージのインストール
pip install package_name

rem インストール済のパッケージ一覧
pip list

rem インストール済のpackage_nameパッケージについて詳細表示
pip show package_name

rem パッケージpackage_nameをアンインストール
pip uninstall package_name

rem 依存関係のチェック
pip check

rem 今のpythonの構成をエクスポート
pip freeze

rem freezeしたテキストファイルをインポートしてインストール
pip install -r freeze.txt
  • pipのオプションはこちらから確認できます
  • インストールできるパッケージはPyPIで公開されています
    • 個別にダウンロードしてきたファイルをインストールする場合も、pip install /path/to/fileでインスト―ルできます
  • プロキシ環境下でインストール作業を行う場合、オプションからプロキシの設定が可能です
    • pip install packagename –proxy http://account_name:password@proxyserver:port
    • パスワードに記号が入る場合はURLエンコードする必要があります

Windows x86-64 embeddable zip file の使い方

Pythonのダウンロード時に選択できる「Windows x86-64 embeddable」のzipファイルからPython環境を構築する手順になります。まずは以下のファイルをダウンロードします。

  • Pythonのダウンロード
    • 該当するCPUの「Windows embeddable package」をダウンロードし展開します
  • get-pipのダウンロード
    • embeddable packageにはpipが含まれていないためpipをインストールする用途です

zipファイルを展開した中にあるpython3xx._pthファイルをテキストエディタで開き、「# import site」をコメントインしてください。次にzipファイルを展開したディレクトリにget-pip.pyファイルを移動してコマンドラインから「python get-pip.py」を実行します。

「Successfully installed pip-xx.x.x setuptools-xx.x.x wheel-x.xx.x」のようなログが出ていればpipのインストールも完了です。

TIPS

基底クラスを呼ぶ

class BaseClass(object):
    def __init__(self, name):
        self.name = name
class InheritClass(BaseClass):
    def __init__(self):
        super(InheritClass, self).__init__('name')

Enum

定義の仕方です。

import enum
class ReturnCode(enum.IntEnum):
    NormalEnd = 0
    WarningEnd = 1
    AbnormalEnd = 2

数値に変換する方法です。

return int(ReturnCode.NormalEnd)

リスト・連想配列のアンパック

list = [1, 2, 3]
print(*list) # 1 2 3

文字列フォーマット

print('this is {0}.'.format('test')))

文字列繰り返し

print('-' * 50)

日時パース

dt_data = '20200102235859'
dt = datetime.datetime.strptime(dt_data, '%Y%m%d%H%M%S')

日時フォーマット

import datetime
now = datetime.datetime.now()
f = now.strftime('%Y%m%d%H%M%S')
print(f)  # 20230828070052

ファイル入出力

# 入力
file = 'C:/test.txt'
data = ''
with open(file, 'r', encoding='utf-8') as f:
    data = f.read()

# 出力
data = 'test'
with open(file, 'w', encoding='utf-8') as f:
    f.write(data)

デバッグログ出力

import logging
 
log_level = logging.DEBUG
log_format = '%(asctime)s- %(name)s - %(levelname)s - %(message)s'
log0 = logging.getLogger(__name__)
log0.setLevel(log_level)
sh = logging.StreamHandler()
sh.setLevel(log_level)
sh.setFormatter(logging.Formatter(log_format))
log0.addHandler(sh)
fh = logging.FileHandler(filename='c:/test.log', encoding='utf-8')
fh.setLevel(log_level)
fh.setFormatter(logging.Formatter(log_format))
log0.addHandler(fh)
 
log0.info('infoメッセージ')
log0.error('errorメッセージ')
  • 標準出力とファイルの双方にログを出力している例です

バッチ処理のパラメータ制御

import argparse
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-s', '--longname', dest=parameter1, default='default value of parameter1', help='parameter1の説明です.')
parser.parse_args()
  • デフォルトで入っているライブラリargparseを使っています
  • parser.add_argumentでパラメータの名前とデフォルト値、説明を追加しています
    • 必須なのか型は何なのかも定義可能です
  • add_helpはargparseが生成するヘルプを使うかどうかです

暗号化・復号化

以下はpycryptodomeパッケージを利用したものとなります。他にも暗号化・復号化パッケージはいくつかあるものの、pycryptoは更新停止、pyca/cryptographyは使い方が難しそうだったりしたので採用しました。

以下はAES(CBCモード)で暗号化する例です

# python -m pip install pycryptodome
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
 
password = 'crypt_key_12'.encode('utf-8')
data = 'テスト'.encode('utf-8')
 
cipher = AES.new(password, AES.MODE_CBC)
ct_bytes = cipher.encrypt(pad(data, AES.block_size))
iv = base64.b64encode(cipher.iv).decode('utf-8')
ct = base64.b64encode(ct_bytes).decode('utf-8')
 
print(ct)

以下はAES(CBCモード)で復号化する例です

# python -m pip install pycryptodome
import base64
from Crypto.Cipher import AES
 
password = 'crypt_key_12'.encode('utf-8')
data = 'xxxx'
 
base64decoded_data = base64.b64decode(data)
iv = base64decoded_data[0:len(password)]
encrypted_data = base64decoded_data[len(password):]
cipher = AES.new(password, AES.MODE_CBC, iv)
decrypted_data = cipher.decrypt(encrypted_data)
 
print(decrypted_data.decode('utf-8'))

POST/GET

# POST
import requests
response = requests.post('http://www.example.com', data={'foo': 'bar'})
print(response.status_code)
print(response.text)

# GET
import requests
response = requests.get('http://www.example.com')
print(response.status_code)
print(response.text)

型チェック

# 整数かどうか
print(isinstance(var, int))

# 小数かどうか
print(isinstance(i, float))

mod-wsgiのインストール中にエラーが発生

「RuntimeError: No Apache installation can be found. Set the MOD_WSGI_APACHE_ROOTDIR environment to its location.」エラーが発生する場合、環境変数にApacheのパスを指定するとうまくいきます。

set MOD_WSGI_APACHE_ROOTDIR=C:\apache

「apr_network_io.h(29): fatal error C1083: include ファイルを開けません。’apr_perms_set.h’:No such file or directory」エラーが発生する場合、必要なインクルードヘッダファイルがありません。

ここからダウンロードしたソースファイルにあるincludeディレクトリからエラーのあったヘッダファイルをapache\includeにコピーします。

リンク

JavaScript

jQuery

セレクター

// 全て
$("*");

// 要素
$('tr');
$('div');

// 要素(ある属性を持つ)
$('tr[name]');

// 要素(ある属性のある値を持つ)
$("tr[name1='value1']");
$("tr[name1='value1'][name2='value2']");

// 要素(ある属性のある値を持たない)
$("tr[name1!='value1']");

// 要素(後方一致)
$("tr[name1$='ue1']");

// 要素(部分一致)
$("tr[name1*='ue']");

// 要素(単語の完全一致)
$("tr[class~='test_class']");

// ID指定
$('#IdName');

// クラス指定
$('.ClassName');

// 複数指定(AND)
$('.ClassName1.ClassName2');

// 複数指定(OR)
$('.ClassName1, .ClassName2');

// SELECT要素で選択されたオプションだけ
$('#select_element option:selected').val();

// SELECT要素で選択されたオプションの属性を取得
$('#select_element option:selected').attr('attirbute1');

// イベント登録
$('.class_name').on('click', function(param1, param2){
  // do something.
});

// イベント削除
$('.class_name').off('click');

// イベントを呼ぶ
$('.class_name').trigger('click', [param1, param2], function(param1, param2){
  // 処理
});

// 表示
$('.class').show();

// 非表示
$('.class').hide();

// 表示されているか
$('.class').is(':visible');

// 表示されていないか
$('.class').is(':hidden');

// DOM追加
$('ul').append('<li>追加されました</li>');
$('<li>追加されました</li>').appendTo('ul');

// 属性追加/変更
$('<div>').attr('id', 'div_id');

// 削除
$('<div>').removeAttr('id');

イベント

イベント説明
blur要素がフォーカスを失った時に発生
focus要素がフォーカスを得た時に発生
loadドキュメント内の全リソースの読み込みが完了したときに発生
resizewindowの大きさが変更された時に発生
scrollドキュメントがスクロールした時に発生
clickクリックされた時
dblclickダブルクリックされた時
mousedown要素上でマウスが押された時に発生
mouseup要素上でマウスが押され、上がった時に発生
mousemove要素上でマウスが移動している時に発生
mouseoverマウスが要素に入った時に発生。子要素でも発生
mouseoutマウスが要素から外れた時に発生。子要素でも発生
mouseenterマウスが要素に入った時に発生。子孫要素に入った時には発生しない
mouseleaveマウスが要素から外れた時に発生。子孫要素から外れた時には発生しない
change要素がフォーカスを得て値の修正が完了した時に発生
selecttype属性値が”text”のinput要素、textarea要素のテキストが選択された時に発生
submitフォームが送信された時に発生
keydownキーが押し下げられた時に発生
keypressキーが押された時に発生
keyupキーが上がった時に発生
errorjavascriptのエラーが発生した時に発生

Linux

コマンド

chmod

パーミッションを設定します。

# 単一ディレクトリのパーミッションを設定する
chmod a+w /home/user/test
 
# 下位ディレクトリも再帰的に設定する
chmod -R a+w /home/user/test
  • ターゲット
    • a: 全て
    • u: 所有者
    • g: グループ
    • o: その他
  • パーミッション
    • r: 読み取り
    • w: 書き込み
    • x: 実行

free

ディスクの空き容量を表示します。

free
free -h
  • -h
    • GBやMBで表示してくれる
  • 結果の見方
    • total
      • マシンのメモリ量
    • used
      • OS/アプリに割り当て済みの量
    • free
      • 純粋な未使用のメモリ
    • shared
      • 共有メモリ
    • buffer
      • カーネルバッファ、メモリ上のデータをデバイスに送受信する領域
    • cached
      • ページキャッシュやスラブキャッシュ(高速化のためのキャッシュ)
    • available
      • free+buffer/cacheのうち解放可能なメモリ
      • これが現時点で使えるメモリ量

vi

  • 行番号
    • 表示: :set number
    • 非表示: :set nonumber
  • 検索
    • 文字検索: /文字列
    • 次の候補: n
  • 再読み込み
    • 再読み込み: :e
    • 強制再読み込み: :e!

curl

curl -s -H "User-Agent: test/1.0" -w 'url: %{url}, time_total: %{time_total}, http_code: %{http_code}\n' -o /dev/null https://www.google.co.jp > ~/test.log
  • -s
    • サイレント、ダウンロード状況等を省略してくれます
  • -H
    • ヘッダ
    • 複数ある場合は-Hを繰り返します
  • -w
    • 指定フォーマットで出力してくれます
    • フォーマットはWrite outが参考になります
      • %{content_type} the Content-Type of the requested document, if there was any.
      • %{errormsg} the error message from the transfer. Empty if no error occurred. (Introduced in 7.75.0)
      • %{exitcode} the numerical exit code from the transfer. 0 if no error occurred. (Introduced in 7.75.0)
      • %{filename_effective} the ultimate filename that curl writes out to. This is only meaningful if curl is told to write to a file with the –remote-name or –output option. It’s most useful in combination with the –remote-header-name option.
      • %{ftp_entry_path} the initial path curl ended up in when logging on to the remote FTP server.
      • %{http_code} the old variable name for what is now known as response_code.
      • %{http_connect} the numerical code that was found in the last response (from a proxy) to a curl CONNECT request.
      • %{http_version} The http version that was used.
      • %{json} all write-out variables as a single JSON object.
      • %{local_ip} the IP address of the local end of the most recently done connection—can be either IPv4 or IPv6
      • %{local_port} the local port number of the most recently made connection
      • %{method} HTTP method the most recent request used
      • %{num_connects} the number of new connects made in the recent transfer.
      • %{num_headers} number of response headers in the last response
      • %{num_redirects} number of redirects that were followed in the request.
      • %{onerror} if the transfer ended with an error, show the rest of the string, otherwise stop here. (Introduced in 7.75.0)
      • %{proxy_ssl_verify_result} the result of the SSL peer certificate verification that was requested when communicating with a proxy. 0 means the verification was successful.
      • %{redirect_url} the actual URL a redirect would take you to when an HTTP request was made without -L to follow redirects.
      • %{remote_ip} the remote IP address of the most recently made connection—can be either IPv4 or IPv6.
      • %{remote_port} the remote port number of the most recently made connection.
      • %{response_code} the numerical response code that was found in the last transfer.
      • %{scheme} scheme used in the previous URL
      • %{size_download} the total number of bytes that were downloaded.
      • %{size_header} the total number of bytes of the downloaded headers.
      • %{size_request} the total number of bytes that were sent in the HTTP request.
      • %{size_upload} the total number of bytes that were uploaded.
      • %{speed_download} the average download speed that curl measured for the complete download in bytes per second.
      • %{speed_upload} the average upload speed that curl measured for the complete upload in bytes per second.
      • %{ssl_verify_result} the result of the SSL peer certificate verification that was requested. 0 means the verification was successful.
      • %{stderr} – makes the rest of the output get written to stderr.
      • %{stdout} – makes the rest of the output get written to stdout.
      • %{time_appconnect} the time, in seconds, it took from the start until the SSL/SSH/etc connect/handshake to the remote host was completed.
      • %{time_connect} the time, in seconds, it took from the start until the TCP connect to the remote host (or proxy) was completed.
      • %{time_namelookup} the time, in seconds, it took from the start until the name resolving was completed.
      • %{time_pretransfer} the time, in seconds, it took from the start until the file transfer was just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved.
      • %{time_redirect} the time, in seconds, it took for all redirection steps including name lookup, connect, pre-transfer and transfer before the final transaction was started. time_redirect the complete execution time for multiple redirections.
      • %{time_starttransfer} the time, in seconds, it took from the start until the first byte was just about to be transferred. This includes time_pretransfer and also the time the server needed to calculate the result.
      • %{time_total} the total time, in seconds, that the full operation lasted. The time will be displayed with millisecond resolution.
      • %{url} the URL used in the transfer. (Introduced in 7.75.0)
      • %{url_effective} the URL that was fetched last. This is particularly meaningful if you have told curl to follow Location: headers (with -L).
      • %{urlnum} the 0-based numerical index of the URL used in the transfer. (Introduced in 7.75.0)
    • -o
      • 出力先、ファイル指定
      • -o /dev/nullとすると標準出力に出力してくれます

date

date "+%Y-%m-%d %H:%M:%S"

rsyslog

システムログの管理ツールで、各プログラムからuser・mail、local0~7といったファシリティごとにログデータの入力を受け付け、設定に従って/var/log等のログファイルにログを出力してくれます。

*.info;mail.none;authpriv.none;cron.none;local0.none;local1.none    /var/log/messages
 
local0.err;local1.err                                   /var/log/error_log
local1.*                                                /var/log/local1_log
  • ファシリティlocal0・local1は/var/log/messagesに出力しないようnoneを設定
  • ファシリティlocal0・local1のエラーログを/var/log/error_logに出力
  • ファシリティlocal1の全てのログを/var/log/local1_logに出力

デーモンを再起動することで設定が反映されます。

sudo systemctl restart rsyslog sudo systemctl status rsyslog

特定の条件のログを捨てたい

例えばApacheの「AH01630: client denied by server configuration」とかを捨てたいケースであれば、rsyslog.confを以下のように記述すると可能です。

if $msg contains 'AH01630: client denied by server configuration' then ~
local0.err;local1.err                                   /var/log/error_log
  • この場合はif文より下にあるログファイルには捨てられた状態でログが伝搬していくので注意が必要です
    • そのログを捨てたくない場合はif文より上に書かないといけません

logrotate

ログのローテーションを管理しているプログラムです。以下の例は/var/log/test_logにログを出力しているファイルに着いてローテーションさせる例です。

/var/log/test_log
{
  missingok
  nocompress
  create
  daily
  ifempty
  dateext
  maxage 14
  postrotate
    /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
  endscript
}
  • /etc/logrotate.dの下に該当するログファイル名でログローテーションの設定ファイルを置くのがルールのようです
  • パラメータ設定の意味
    • missingok:ファイルがなくてもエラーとして扱わない
    • nocompress:gzip圧縮しない
    • create:新規作成する
    • daily:日次で作成する
    • ifempty:ログファイルが空でもローテーションする
    • dateext:ローテーションしたログファイル名にYYYYMMDDを追加
    • maxage 14:ローテーションファイルは14日間(2週間)
    • postrotate:ローテーション後にsyslogd再起動(未指定の場合はローテーションファイルにログが出力され続ける)

以下のコマンドで動作確認できます。

sudo logrotate -fd /etc/logrotate.d/test_log

スワップファイルの作成

swapoff /swapfile
rm -f /swapfile
fallocate -l 1G /swapfile
chmod a+rw /swapfile
mkswap /swapfile
swapon /swapfile

デーモンのリスト確認

sudo systemctl list-units

シェルでのループ

#!/bin/bash
 
echo "----------" >> /usr/local/loop_access.log
date "+%Y-%m-%d %H:%M:%S" >> /usr/local/loop_access.log
for i in {1..10}
do
  curl -s -H "User-Agent: xxxx/1.0" -o /dev/null -w 'url: %{url}, http_code: %{http_code}, exitcode: %{exitcode}\n' https://xxxx >> /usr/local/loop_access.log
done

Windows

標準入力をバッチで行う

echo Y | del folder\*

カレントディレクトリをバッチファイルのパスにする

cd /d %~dp0
  • %~dp0
    • ~:ファイルパスからダブルクォーテーションを除去
    • d:ドライブ文字を含む
    • p:パスを含む
    • 0:%0はそのバッチファイルまでのパス(ダブルクォーテーションで囲まれたパス)
  • C:\test\test.batで「%~dp0」を指定した場合
    • 「C:\test\」となります

ディレクトリを作りながらファイルコピーする

echo F | xcopy /Y C:\src_dir1\src_dir2\source.txt C:\dest_dir1\dest_dir2\dest.txt

コマンドプロンプトのコードページ変更

chcpを使う場合

chcp [num]
  • UTF8
    • chcp 65001
  • SJIS
    • chcp 932

環境変数を使う場合

set LANG=ja_JP.UTF-8

特定のコマンドでディレクトリ中のファイルリストを処理する

@echo off
for %%i in (*.txt) do (
  echo ファイル名:%%i
  mysql.exe -hlocalhost -uuser_name -ppassword -P3306 database_name < %%i
)

テキストファイルをn行ごとに分割してファイル出力

$i=1; cat -Encoding UTF8 .\many_line_file.txt -ReadCount 1000 | % { $_ > many_line_file_$i.txt;$i++ }

指定ディレクトリのサブディレクトリを一括削除

for /F %a in ('dir /AD /B /W C:\test\*') do rmdir /S /Q C:\test\%a

ドライブの空き容量

fsutil volume diskfree C:

アカウントの状態確認

t user {アカウント名} /domain

ポート使用プログラムの確認

rem ポート使用PIDを探す
netstat -ano
 
rem PIDからプログラムを探す
tasklist /svc /fi "PID eq 20840"

タスクスケジューラ操作

schtasksコマンドを利用して行います。

タスクスケジューラ登録

rem 毎日0:00に実行
schtasks /Create /RU .\Administrator /RP password /SC DAILY /TN "タスク名" /TR "D:\bin\task.bat" /ST 00:00 /F /RL HIGHEST

rem 毎週日曜日に実行
schtasks /Create /RU .\Administrator /RP password /SC WEEKLY /D SUN /TN "タスク名" /TR "D:\bin\task.bat" /ST 01:15 /F /RL HIGHEST

rem 毎日9:00~22:00の間、1時間おきに実行
schtasks /Create /RU .\Administrator /RP password /SC DAILY /TN "タスク名" /TR "D:\bin\task.bat" /ST 09:00 /RI 60 /ET 21:59 /F /RL HIGHEST

タスクスケジューラ削除

schtasks /delete /tn "タスク名"

サービス削除

rem サービスの確認
sc query

rem 該当サービスの削除
sc delete service_name

ミラーリングしたコピー

robocopy C:\xxx E:\xxx /MIR /E /V /XJ

タスクバーの場所

タスクバーにピン止めしているショートカットの実体は以下のフォルダにあります。

C:\Users\{ユーザー名}\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar

Windowsで任意のプログラムをサービス化する

WinSWというプログラムを用いて実現可能です。こちらから該当するプラットフォーム(64bitならWinSW-x64.exe)のファイルをダウンロードして任意の名前にリネームします。その後、リネームしたexe名と同じxmlファイルを作成し、そこに設定を追記します。

今回はApache Solrをサービス化しようとして、まずダウンロードしたWinSW-x64.exeをsolr.exeに変更し、その後にsolr.xmlを作成しました。以下はそのxmlファイルとなります。

<service>
  <id>solr</id>
  <name>Apache Solr</name>
  <description>Solr is the popular, blazing-fast, open source enterprise search platform built on Apache Lucene.</description>
  <env name="SOLR_HOME_DIR" value="C:\application\solr"/>
  <executable>%SOLR_HOME_DIR%\bin\solr.cmd</executable>
  <arguments>start -f</arguments>
  <stopexecutable>%SOLR_HOME_DIR%\bin\solr.cmd</stopexecutable>
  <stoparguments>stop -all</stoparguments>
  <logmode>rotate</logmode>
</service>
  • サービス登録は「solr install」で実行します
  • サービス削除は「solr uninstall」で実行します
  • 余談

ALT+TAB切替でブラウザのタブを表示させたくない

ALT+TABでアプリケーション切り替えができますが、ブラウザで複数タブを表示しているとそれぞれのタブが切替候補で表示されて鬱陶しい時があります。

以下の手順でタブをALT+TABの切替候補から外せます。

  • Windowsの設定アプリを開く
    • タスクバーの歯車アイコンクリック
    • スタートキーの後に「設定」と入力してエンターキー 等
  • 左メニュー「システム」
  • 右メニュー「マルチタスク」
  • 右にある「スナップまたはAlt+Tabを押したときにアプリのタブを表示する」を「タブを表示しない」に設定

Java

ヒープ最小・最大メモリの指定方法

javaの起動パラメータに-Xms(最小)、-Xmx(最大)以下のオプションを追加することで可能です。

java xxx -Xms512m -Xmx512m

環境変数_JAVA_OPTIONSに指定することでも可能です。

set _JAVA_OPTIONS=-Xms512M -Xmx512M
java xxx
  • 適用の優先順位は環境変数>実行時パラメータです

以下は動作確認用のコードです。

/*
各種環境変数をセットして実行
set _JAVA_OPTIONS=-Xms12M -Xmx12M
set _JAVA_OPTS=-Xms24M -Xmx24M
set JAVA_OPTIONS=-Xms36M -Xmx36M
set JAVA_OPTS=-Xms48M -Xmx48M
javac JavaMemory.java && java -Xms128M -Xmx128M JavaMemory
*/
import java.text.NumberFormat;
 
public class JavaMemory {
  public static void main(String[] args) {
    Runtime r = Runtime.getRuntime();
    System.out.println("version     : " + System.getProperty("java.version"));
    System.out.println("maxMemory   : " + NumberFormat.getNumberInstance().format(r.maxMemory()));
    System.out.println("totalMemory : " + NumberFormat.getNumberInstance().format(r.totalMemory()));
    System.out.println("freeMemory  : " + NumberFormat.getNumberInstance().format(r.freeMemory()));
  }
}

Oracle

スキーマ一覧

SELECT DISTINCT owner FROM all_objects ORDER BY owner

新規ユーザ作成

DROP USER {USERNAME} cascade;
CREATE USER {USERNAME} IDENTIFIED BY {PASSWORD} DEFAULT tablespace USERS TEMPORARY tablespace TEMP;
SELECT * FROM all_users;

新規ユーザへの権限付与

GRANT CONNECT TO {USERNAME};  -- 接続
GRANT resource TO {USERNAME};
GRANT unlimited tablespace TO {USERNAME}; -- 表領域の変更
GRANT CREATE TABLE TO {USERNAME};
GRANT DROP any TABLE TO {USERNAME};
GRANT CREATE VIEW TO {USERNAME};
GRANT DROP any VIEW TO {USERNAME};
GRANT SELECT any TABLE TO {USERNAME};
GRANT INSERT any TABLE TO {USERNAME};
GRANT UPDATE any TABLE TO {USERNAME};
GRANT DELETE any TABLE TO {USERNAME};
GRANT CREATE PROCEDURE TO {USERNAME};
GRANT DROP any PROCEDURE TO {USERNAME};
GRANT ALTER any PROCEDURE TO {USERNAME};
GRANT EXECUTE any PROCEDURE TO {USERNAME};
GRANT CREATE any directory TO {USERNAME};

ディレクトリオブジェクトの作成

DROP directory SAVE_DIR;
CREATE OR REPLACE directory SAVE_DIR AS 'C:\temp';
GRANT READ ON directory SAVE_DIR TO {USERNAME};
GRANT WRITE ON directory SAVE_DIR TO {USERNAME};
SELECT * FROM all_directories;
  • 該当ディレクトリ({MACHENE_NAME}\ORA_OraDB12Home1_DBA)へのアクセス権を付与が必要です

ログインユーザーが持つテーブル一覧

SELECT * FROM user_tables;

テーブル行数

SELECT TABLE_NAME, num_rows FROM user_tables ORDER BY TABLE_NAME;

sqlplus

cd C:\app\username\virtual\product\12.2.0\dbhome_1\bin
sqlplus.exe {USERNAME}/{PASSWORD}@{DBNAME} @C:\sample.sql
  • 日時の文字列フォーマットは環境変数「NLS_DATE_FORMAT」に登録して利用する
    • set NLS_DATE_FORMAT=YYYY-MM-DD HH24:MI:SS

エクスポート

cd C:\app\username\virtual\product\12.2.0\dbhome_1\bin
expdp.exe system/{PASSWORD}@{DBNAME} content=ALL tables=tablename directory=SAVE_DIR dumpfile=tablename.dmp logfile=tablename.log

インポート

cd C:\app\username\virtual\product\12.2.0\dbhome_1\bin
impdp.exe {USERNAME}/{PASSWORD}@{DBNAME} content=ALL table_exists_action=REPLACE REMAP_SCHEMA=(SYSTEM:{USERNAME}) dumpfile=accounts.dmp directory=SAVE_DIR tables=accounts

create table select * from xxx

CREATE TABLE new_tablename AS SELECT * FROM old_tablename;

直近に発行したSQLとパラメータを知りたい

SYS権限のあるユーザでログインしている前提で以下のSQLを実行します。

SELECT SQL_ID,FIRST_LOAD_TIME,SQL_TEXT
FROM V$SQL
WHERE FIRST_LOAD_TIME BETWEEN TO_CHAR(SYSDATE - (5 / 24 / 60), 'YYYY-MM-DD/HH24:MI:SS') AND TO_CHAR(SYSDATE, 'YYYY-MM-DD/HH24:MI:SS')
ORDER BY FIRST_LOAD_TIME DESC;

Nullと空文字

Oracleは空文字をNullと見なすため、抽出条件において他のDBMSと異なる挙動を示すことがあります。

SELECT CASE WHEN 'xxxx' <> '' THEN 1 ELSE 0 END FROM dual;
-- 0を返す

そのため以下のように回避します。

SELECT CASE WHEN nvl(column_a, '') || 'x' <> nvl(colum_b, '') || 'x' THEN 1 ELSE 0 END FROM dual;

Docker

DockerFileからDockerイメージを作成

# mkdir ./work
# cd ./work
# cat > Dockerfile <<EOF
FROM centos:7
RUN yum install -y httpd
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]
EOF
# docker build -t my-app:latest .
# docker images

イメージ取得

docker pull centos:centos8

コンテナ稼働

docker run --detach --name image_name --privileged -p 80:80 -p 443:443 -v C:/htdocs:/home/opuser/htdocs image_name /sbin/init
  • -p: ポートフォワード
    • 複数の場合は-pオプションを複数つけていきます
  • -v: ホストのディレクトリをコンテナのディレクトリに紐づけます
    • ホスト:コンテナ
  • image_nameのところはイメージIDでもいいようです

コンテナ接続

docker exec -it image_name bin/bash

ホストからコンテナにファイルコピー

docker cp ImageMagick-7.0.11-6.x86_64.rpm image_name:/home/ImageMagick-7.0.11-6.x86_64.rpm

コンテナをエクスポート

docker export image_name > image_name.tar

コンテナをインポート

docker import image_name.tar

built中に「max depth exceeded」エラーが出る

dockerイメージの構築時にdockerはレイヤーという単位で処理を行っているらしく、最大レイヤー数を超えると上記エラーが出力されるようです。

RUN/COPY/ADDコマンドを使うとレイヤーが増えてしまいます。そのためなるべくレイヤーが増えないように工夫をする必要がありました。例えば以下のような方法です。

  • RUNは&&でつなぐ
  • COPYはファイル単位ではなくディレクトリ単位でコピーする

built中に出力が止まる

ディスク容量が足りなくなって止まっていると思われます。コンテナ/イメージの削除をしてもディスク容量が減らないことがあったため、以下を試しました。

  • Docker for Windows画面を起動させ、右上のバグアイコンをクリック、表示される「Troubleshoot」画面で「Clean / Purge data」のボタンを押します
  • 表示される3項目の全てをチェックし実行します

Exitしたコンテナの中に入って原因を探りたい

止まったコンテナのコンテナIDを取得します。

docker ps -a

止まったコンテナからイメージを作成します。

docker commit -m exited xxxx

記コマンドの実行結果sha256の値をメモしてdockerイメージを起動します。

docker run -u root --rm -it xxxx /bin/bash

Solrコンテナにrootで入りたい

sudo docker exec -u root -it xxxx /bin/bash

KATE(Windows)

KDEのテキストエディタであるKATEにはWindows版があります。WindowsのストアからKATEをインストールした場合、オリジナルのハイライト設定ファイルを作成するのは以下のディレクトリでした。

  • %USERPROFILE%\AppData\Local\Packages\KDEe.V.Kate_7vt06qxq7ptv8\LocalCache\Local\org.kde.syntax-highlighting\syntax

以下は試しに作ったハイライト設定ファイルです。これをKATEの設定→Color Themeで新しく定義したカラーテーマに合わせて色を設定していきます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd">
<language name="Novel Files" section="Configuration" extensions="*.txt" mimetype="" version="1.1" kateversion="2.0" author="Kenichi Matsuda (kenichi.matsuda.g@gmail.com)" license="LGPL">
 
	<highlighting>
		<contexts>
			<context name="novel" attribute="Normal Text" lineEndContext="#stay">
				<RegExpr attribute="Chapter" context="#stay" String="^\[[^\[\]]+\]$"/>
				<RegExpr attribute="Section" context="#stay" String="^[\$\@].+$"/>
				<RegExpr attribute="Warning" context="#stay" String="^\%.+$"/>
				<RegExpr attribute="Comment" context="#stay" String="^#.+$"/>
				<RegExpr attribute="Selif" context="#stay" String="^.+[::]"/>
				<RegExpr attribute="Url" context="#stay" String="(http|https|ftp)\:[a-zA-Z0-9-_\.\/%]+"/>
				<RegExpr attribute="Quote" context="#stay" String="^\>.+$" />
			</context>
		</contexts>
 
		<itemDatas>
			<itemData name="Normal Text" defStyleNum="dsDataType" />
			<itemData name="Chapter" defStyleNum="dsKeyword" />
			<itemData name="Section" defStyleNum="dsKeyword" />
			<itemData name="Warning" defStyleNum="dsKeyword" />
			<itemData name="Comment" defStyleNum="dsComment" />
			<itemData name="Selif" defStyleNum="dsKeyword" />
			<itemData name="Url" defStyleNum="dsKeyword" />
			<itemData name="Quote" defStyleNum="dsKeyword" />
		</itemDatas>
 
	</highlighting>
 
</language>

Apache

構文チェック

Windows

httpd.exe -S

Linux

sudo apachectl configtest

ログの出力先をsyslogに変更

# エラーログ
#ErrorLog "logs/error_log"
ErrorLog syslog:local1

# アクセスログ
<IfModule log_config_module>
CustomLog "|/usr/bin/logger -p local0.info -t httpd_access" combined
</IfModule>

デーモン再起動で反映します。

sudo systemctl restart httpd sudo systemctl status httpd

エラーログの動作確認は激しく長いURLを入力すれば確認できます。アクセスログは普通にアクセスすることで確認できます。

複数ドメインを1サーバーで稼働させたい

httpd.confでバーチャルホスト用の設定をコメントインします。(後述のhttpd-vhosts.confの内容をそのままhttpd.confに記述することも可能です)

# 以下をコメントイン
Include conf/extra/httpd-vhosts.conf

次にhttpd-vhosts.confにドメインごとのバーチャルホストの設定を追加します。

<VirtualHost *:80>
    ServerName  site_a.domain.com
    DocumentRoot "C:/htdocs/application1"
</VirtualHost>
<VirtualHost *:80>
    ServerName  site_b.domain.com
    DocumentRoot "C:/htdocs/application2"
</VirtualHost>

IPアドレスによるアクセス制限

以下はバーチャルホストでの設定例です。

<VirtualHost _default_:443>
    DocumentRoot "/var/www/site"
    # 許可するIPアドレスを変数で指定する
    Define IP_OK_1 192.168.1.1
    <Location "/">
        Require all denied
        Require ip 127.0.0.1
        Require ip ::1
        # リクエストのあったIPアドレスが許可されているものならOKとする
        Require expr req('X-Forwarded-For') -strmatch "${IP_OK_1}"
    </Location>
    # ヘルスチェック用のhtmlはユーザエージェントで判断してアクセス許可をする
    <Location "/index.html">
        Require all denied
        Require expr %{HTTP_USER_AGENT} -strmatch 'ELB-HealthChecker/2.0'
    </Location>
</VirtualHost>

WebDAV環境構築

特定のディレクトリに対しBasic認証で認証し、WebDAVでファイルのダウンロード/アップロードを行えるようにする流れとなります。(主にWebDAVアクセスプログラムの動作用サーバーとして設定した程度ですので、セキュリティ的な面は考慮していません)

httpd.confで以下を実施します。

  • WebDAVモジュールの有効化
  • WebDAV用設定ファイル読み込み
  • WebDAV用ディレクトリ設定
# WebDAVモジュールの有効化
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule dav_lock_module modules/mod_dav_lock.so

# WebDAV用設定ファイル読み込み
Include conf/extra/httpd-dav.conf

# WebDAV用ディレクトリ設定
<Directory "C:/htdocs/test/webdavtest">
    Options All -Indexes +SymLinksIfOwnerMatch -FollowSymLinks
    AllowOverride All
</Directory>

http-dav.confで以下を実施します。

  • DavLockDBファイルのパス設定
  • エイリアス設定
  • WebDAVディレクトリ設定
# DavLockDBファイルのパスを設定
DavLockDB "C:/htdocs/test/webdavtest/DavLock"

# エイリアスの設定
Alias /uploads "C:/htdocs/test/webdavtest/uploads"

# WebDAVディレクトリの設定
<Directory "C:/htdocs/test/webdavtest/uploads">
    Dav On
    Options None
    AuthType Basic
    AuthName "webdavuser"
    AuthUserFile C:\htdocs\test\webdavtest\basicauth.txt
    Require valid-user
</Directory>

Apacheのhtpasswd.exeを使って基本認証のユーザ名/パスワードを生成します。

C:\> cd C:\apache\bin
C:\apache\bin> htpasswd.exe -c C:\htdocs\test\webdavtest\basicauth.txt webdavuser
New password: **************
Re-type new password: **************
Adding password for user webdavuser

これでWebDAV環境の構築完了です。ユーザ名webdavuser、上記で設定したパスワードを用いてBasic認証をし、ファイルをダウンロードする場合はGETリクエスト、ファイルをアップロードする場合はPUTリクエストを行うことでWebDAVのアクセスが確認できると思います。

起動時に「nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation」エラーが出る

Apache2+PHP8.1で稼働させていたのですが、PHP8.2にバージョンアップさせたタイミングで発生しました。

Apacheの最新バージョンをインストールすることで解消しました。そのさいに*.confもきちんと最新バージョンに合わせて移行しないといけないので注意が必要です。

MeCab

Linux上でビルドとインストールを行い、Pythonによる簡単な実装での動作確認例となります。

まずはGCCのインストールからとなります。

yum install gcc gcc-c++ make

次にMeCabのソースをダウンロードしてビルドします。

cd /usr/local/src/
wget 'https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7cENtOXlicTFaRUE' -O mecab-0.996.tar.gz
tar zxvf mecab-0.996.tar.gz
cd mecab-0.996
./configure --with-charset=utf8 --enable-utf8-only
make
make install
mecab --version

MeCab用の辞書をダウンロードしてビルドします。

cd /usr/local/src/
wget 'https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7MWVlSDBCSXZMTXM' -O mecab-ipadic-2.7.0-20070801.tar.gz
tar zxvf mecab-ipadic-2.7.0-20070801.tar.gz
cd mecab-ipadic-2.7.0-20070801
./configure --with-charset=utf8
make
make install
 
chmod a+r /usr/local/lib/mecab/dic/ipadic/dicrc

コマンドラインから動作確認をします。

# 出力フォーマットyomiと入出力ファイルを指定して実行
mecab in.txt -o out.txt -Oyomi

# 対象文字列は標準入力から読み込み、自分で指定した出力フォーマット(読みだけ)で出力
echo テスト | mecab --node-format=%f[8] --unk-format=%M --eos-format=\n

Pythonでの処理例です。in.txtには漢字で書かれたデータが行ごとに入っており、それをMeCabで読みに変換してout.txtに出力するというものです。MeCabの呼び出しはsubprocessを使っています。

import os
import subprocess
 
converted_lines = []
with open(os.path.join(os.path.dirname(__file__), 'in.txt'), 'r', encoding='utf-8') as f:
    while True:
        line = f.readline()
        if line == '':
            break

        command = r'mecab --node-format=%f[8] --unk-format=%M --eos-format=\n'.format(line)

        cp = subprocess.run(command, shell=True, input=line, text=True, capture_output=True, encoding='utf8')
        if cp.stdout is not None:
            converted_lines.append('{}\t{}\n'.format(line, cp.stdout.strip()))

with open(os.path.join(os.path.dirname(__file__), 'out.txt'), 'w', encoding='utf-8') as f:
    f.writelines(converted_lines)

ImageMagick

CentOSでのインストール方法です。

yum install -y https://download.imagemagick.org/ImageMagick/download/linux/CentOS/x86_64/ImageMagick-libs-7.1.0-2.x86_64.rpm
yum install -y https://download.imagemagick.org/ImageMagick/download/linux/CentOS/x86_64/ImageMagick-7.1.0-2.x86_64.rpm
yum install -y https://download.imagemagick.org/ImageMagick/download/linux/CentOS/x86_64/ImageMagick-devel-7.1.0-2.x86_64.rpm
magick --version

LibreOffice

CentOSでのインストール方法です。

# LibreOffice本体のインストール
yum install libreoffice-langpack-ja libreoffice-draw libreoffice-base libreoffice-impress libreoffice-math libreoffice-writer libreoffice-help-ja libreofficekit
soffice.bin --version

# LibreOfficeが使用する日本語フォントのインストール
wget https://moji.or.jp/wp-content/ipafont/IPAexfont/IPAexfont00401.zip
unzip IPAexfont00401.zip
mkdir /usr/share/fonts/japanese
mkdir /usr/share/fonts/japanese/TrueType
mv IPAexfont00401/*.ttf /usr/share/fonts/japanese/TrueType/
 
wget https://moji.or.jp/wp-content/ipafont/IPAfont/IPAfont00303.zip
unzip IPAfont00303.zip
mv IPAfont00303/*.ttf /usr/share/fonts/japanese/TrueType/
fc-cache -fv
fc-list

Excel→PDF変換(編集不可)

Windows上にインストールされたLibreOfficeでExcel→PDF(編集パスワード付き)を作成する例です。

"C:\Program Files\LibreOffice\program\soffice.exe" --headless --nologo --nofirststartwizard --convert-to "pdf:calc_pdf_Export:{\"EncryptFile\":{\"type\":\"boolean\",\"value\":\"true\"},\"RestrictPermissions\":{\"type\":\"boolean\",\"value\":\"true\"},\"PermissionPassword\":{\"type\":\"string\",\"value\":\"pass\"},\"Changes\":{\"type\":\"long\",\"value\":\"0\"}}" test.xlsx --outdir .\

その他

動画のストリーミング配信

構築したWebサイトで動画を流したい場合、真っ先に思いつくのはHTMLのVIDEOタグを利用する方法だと思います。HTMLにタグ<video src=”xxx.mp4″</video>を入力すれば動画は再生されますし、VIDEOタグ自体はMP4ならほとんどのブラウザでサポートされています。

しかしながらVIDEOタグでの動画再生は「動画ファイル全体をダウンロードしないと再生が始まらない」問題があります。長い動画の場合はファイルサイズがGB単位になってしまい、それを全てダウンロードするまでに数十分と待つユーザーは少ないと思います。

そこでストリーミングによる動画再生ができないか検討したところ、HLS(HTTP Live Streaming)規格による配信ができそうなことが分かりました。

  • HLS(HTTP Live Streaming)は、Apple社が策定したiOS/Android/Webブラウザで再生可能なストリーミング技術の規格で、AbemaTVでも採用されているそうです
  • 概要としては、動画ファイルを細かく分割して次々と相手に読み込ませるというものでした
    • input.mp4という長い動画があるとして、それを例えば5つの001.ts~005.tsという動画ファイルに分割し、それのプレイリスト用としてplaylist.m3u8ファイルを用意します
    • 相手にはplaylist.m3u8を送信し、相手はそのプレイリストの先頭にある001.tsを読み込んで再生しながら、次の002.tsを読み込んで・・・を繰り返すというものでした

HLSをネイティブに対応(VIDEOタグのsrc属性にHLSを指定して読み込む)しているのはSafariだけのようですが、別途hls.jsというライブラリを使うことで他のブラウザでもHLS動画を読み込めるようになります。

まずはHLS動画を作成する必要があります。作成するソフトウェアは色々あるようですが、今回はffmpegで行う例となります。ffmpegのページからダウンロードしてインスト―ルします。(またはこちらの「ffmpeg-release-essentials.zip」をダウンロードして任意のフォルダに展開します)

そして対象の動画ファイルを用意してコマンドを実行します。

ffmpeg -i “C:\test\test_video.mp4” -c:v copy -c:a copy -segment_format mpegts -hls_time 9.0 -break_non_keyframes 0 -hls_list_size 0 -hls_segment_filename “C:\test\hls\test_video-%05d.ts” “C:\test\hls\test_video.m3u8”
  • オプションの説明は以下です
    • -i:入力になる動画ファイル
    • -c:v:コーデックを指定、ここでは元のコーデックを使うよう指示
    • -c:a:音声のコーデックを指定、ここでは元のコーデックを使うよう指示
    • -segment_format:分割ファイルのフォーマット、ここではmpegts(MPEG)を指定
    • -hls_time:9秒ごとに分割
    • -break_non_keyframes:0はセグメントの開始にキーフレームのみ指定
    • -hls_list_size:0はプレイリストに全ての分割ファイルを記載
    • -hls_segment_filename:出力ファイルとファイル名のパターン、ここではtest_video-%05d.ts(%05dは00001~の連番)を指定
    • 出力するプレイリストファイル

このままでもHLS動画が配信可能ですが、暗号化をしないと分割された動画ファイルを保存して他人に渡せるという状態になります。そのあたりを制限したい場合はOpenSSLによる暗号化が可能です。

まずOpenSSLをダウンロードしてインストールします。OpenSSLにてキーを作成します。

 rand -out test_video.key 16

次に初期化ベクトルを作成します。

C:/> openssl rand -hex 16
b3fe659027bc3b007b883974c2d0ed19

これらで作成したデータを使ってtest_video.keyinfoファイルを作成します。

http://localhost/test/test_video.key
C:\test\test_video.key
b3fe659027bc3b007b883974c2d0ed19

このtest_video.keyinfoを使ってffmpegを実行すると、暗号化された分割動画ファイルが作成されます。

ffmpeg -i C:\test\test_video.mp4” -c:v copy -c:a copy -segment_format mpegts -hls_time 9.0 -break_non_keyframes 0 -hls_list_size 0 -hls_key_info_file “C:\test\test_video.keyinfo” -hls_segment_filename “C:\test\hls\test_video-%05d.ts” “C:\test\hls\test_video.m3u8”
  • -hls_key_info_file:上記で作成したkeyinfoファイルです
  • それ以外は前段のオプションと変わっていません

これで作成したファイル群をサーバーに格納します。

次にアクセス用のHTMLを作って動作確認します。

<html>
	<head>
		<meta charset="UTF-8" />
		<script src="hls.js"></script>
	</head>
	<body>
		<video id="test_video" controls preload="metadata" width="640" height="480" />
		<script>
			function setVideo(path)
			{
				var video = document.getElementById('test_video');
				if(video.canPlayType('application/vnd.apple.mpegurl'))
				{
					video.src = path;
					return;
				}
				if(Hls.isSupported())
				{
					var hls = new Hls();
					hls.loadSource(path);
					hls.attachMedia(video);
				}
				return;
			}
			setVideo('/test/hls/test_video.m3u8');
		</script>
	</body>
</html>
  • ブラウザの開発者ツールにあるネットワークを表示したままアクセスし動画を再生すると、次々とアクセスしては動画データを取得しているのが分かると思います
  • hls.jsはこちらからダウンロードして使っています

テスト用のメールアドレス

Gmailではメールアドレスのエイリアスを作成することが可能でした。

例えばtest@gmail.comというアドレスがあるとしたら、そのアカウントの次にプラスから始まる文字列をつけると、そのメールアドレスに送られたメールもtest@gmail.comで受信できます。

  • 以下のメールアドレスに送ったメールがtest@gmail.comの受信トレイで確認できるというものです
    • test@gmail.com
    • test+1@gmail.com
    • test+2@gmail.com
  • 作成できるエイリアスの最大数は30だそうです

この仕組みを使って、複数のメールに送るようなプログラムの動作確認ができると思います。