「Develop」の版間の差分

提供:senooken JP Wiki
(コンストラクターのアクセス権)
(同じ利用者による、間の20版が非表示)
45行目: 45行目:
==== パーマリンク ====
==== パーマリンク ====
Slackの投稿パーマリンクをWebブラウザーで開くと、該当箇所にジャンプできない。デスクトップアプリがあると開ける。それでしのぐ。
Slackの投稿パーマリンクをWebブラウザーで開くと、該当箇所にジャンプできない。デスクトップアプリがあると開ける。それでしのぐ。
=== JIRA ===
==== 関連チケット ====
[修正するバージョン]/[影響するバージョン] のリンクをクリックすると、関連するissueが一覧表示される。これで未クローズチケットを確認するといい。


=== Confluence ===
=== Confluence ===
478行目: 483行目:


コマンドラインからだとopendiff。
コマンドラインからだとopendiff。
==== Visual Studio Code ====
===== About =====
ディレクトリー比較は [[https://marketplace.visualstudio.com/items?itemName=moshfeu.compare-folders Compare Folders - Visual Studio Marketplace]] 拡張機能。 画像比較は [Image Preview] らしい。
[https://www.javadrive.jp/vscode/editor/index3.html VSCode | 2つのファイルの内容を比較して差分を表示する]
code -d <file1> <file2>
上記コマンドで差分表示できる。外部の差分ツールとして使う際は、上記コマンドになるように指定する。
GUIからだと、[View]-[Command Pallete]-[Compare] から比較できる。
比較のモードがいくつかある ([https://zenn.dev/haretokidoki/articles/dae3536ea55f49 VS Codeでファイル・ソースコードの差分を比較(diff)する2通りの方法])。
{| class="wikitable"
!No.
!比較モード
!用途
|-
|1
|ファイル: アクティブ ファイルを比較しています...
File: Compare Active File With...
|現在のアクティブファイル と 指定したファイル を比較する。
|-
|2
|ファイル: クリップボードとアクティブ ファイルを比較
File: Compare Active File with Clipboard
|<code>Ctrl + C</code>でクリップボードに保存された文字列 と 現在のアクティブファイル を比較する。
|-
|3
|ファイル: 新しい無題のテキスト ファイルの比較
File: Compare New Untitled Text Files
|比較モードで新規テキストファイルを2つ開いた状態となる。
|-
|4
|ファイル: 保存済みファイルと作業中のファイルを比較
File: Compare Active File with Saved
|未編集状態のアクティブファイル と 前回保存したアクティブファイル を比較する。
|-
|5
|マージの場合: 現在の競合を比較
Merge Conflict: Compare Current Conflict
|Git環境でブランチをマージした時にコンリクト(競合)が発生していないか比較する。
|}
File: Compare Active File Withが素直か。
===== Diff Folders =====
[https://untic.blog/blogs/468 VSCode拡張機能「Diff Folders」でフォルダ間の違いを簡単に比較しよう! | UNTIC | Web担当者のための仕事メディア]
Diff Foldersの他に、Compare Foldersというのもある。が、Diff Foldersのほうが直感的で使いやすいらしい ([https://stackoverflow.com/questions/70159358/is-there-a-compare-folders-feature-in-vs-code is there a compare folders feature in VS Code? - Stack Overflow])。ただ、Compare Foldersのほうがダウンロード数が多い。
標準ではディレクトリー比較はできない。Diff Foldersの拡張機能が必要。
# Diff Foldersをインストール
# c-P-[Diff Folders]-[New Diff Panel] またはc-L
===== Compare Folders =====
[https://amateur-engineer-blog.com/vscode-compare-folders VSCodeでフォルダ丸ごと比較する]


== Coding ==
== Coding ==
1,113行目: 1,175行目:


<code>map_[key]_[value]</code> のような形式にすると、キーとバリューが何を意味するか分かってわかりやすい。
<code>map_[key]_[value]</code> のような形式にすると、キーとバリューが何を意味するか分かってわかりやすい。
https://chatgpt.com/c/67ca84e0-9018-800b-9674-035ae9f4bbaf
* [key]_[value]_map
* [key]_to_[value]
上記のどちらかがいいだろう。toがkey_valueの区切りが明示的でいいかもしれない。


===== array/foreach =====
===== array/foreach =====
1,164行目: 1,233行目:
<nowiki>https://okwave.jp/qa/q4202225.html</nowiki></blockquote>
<nowiki>https://okwave.jp/qa/q4202225.html</nowiki></blockquote>


==== DB ====
===== get/fetch =====
[http://blog.tojiru.net/article/277021312.html PDOの真の力を開放する - PHPでデータベースを扱う(3): Architect Note]
https://chatgpt.com/c/67bd1a05-d3a0-800b-88d8-f4f47b995560
 
* fetch=外部から取得する意味。DBや外部Web APIから取得する場合にfetchがいい。
* get=手元から取得する意味。プロパティーなど内部から取得する場合。


DBアクセスのモデル化。行をクラスとすると扱いやすい模様。
===== list/data =====
fetchList/fetchDataのどちらがいいか?


getterを作ったり、データの妥当性のチェックなどもできる。
* list=配列。必ず配列。
* data=全部。配列以外にnullや単一データがあるならこちら。


select/insert/などはmapperでクラスとDB列名を対応付けて処理する。自前で実装する場合はこういうつくりがいいらしい。
基本はfetchListでいいと思う。


データベース関係のデザインパターンがいくつかある。
===== Order =====
https://chatgpt.com/c/67ca7edf-f92c-800b-8174-9706bfba3ff3


* Active Record
関数実行の順番が大事なときと、そうでないときがある。区別し難い。
* Data Mapper


===== Active Record pattern =====
順序を明示したい場合、メソッドチェーンを使うのが確実。


* [https://ja.wikipedia.org/wiki/Active_Record Active Record - Wikipedia]
他に、前の関数の結果、戻り値を後続の引数に渡すなら、それも悪くない。
* [https://www.techscore.com/tech/Ruby/Rails/other/designpattern/ デザインパターンから見たActive Record | TECHSCORE(テックスコア)]


テーブルレコードに対応するクラスを用意して、そのクラス自体にDB操作もさせる。
===== privateの先頭_ =====
privateなメソッド、プロパティーで、先頭に_をつけることがある。


シンプルだが、複雑な操作が苦手。
https://chatgpt.com/c/67da92b1-1650-800b-b347-f16f76fd549a


エンティティーがテーブルと密接なため、例えばテーブル構造が変わった場合に大量に修正必要。
privateのアクセス権、可視性の機能があるなら、それを使えばいいので、_は不要。むしろないほうがいいらしい。PHPのPSR-12では禁止されている。


Ruby on Rails/Laravel+Eloquentなどで採用。
「[https://www.php-fig.org/psr/psr-12/ PSR-12: Extended Coding Style - PHP-FIG]」<blockquote>Property names MUST NOT be prefixed with a single underscore to indicate protected or private visibility. That is, an underscore prefix explicitly has no meaning.</blockquote>Pythonのように、言語的にないなら、やむを得ない。


===== Data Mapper pattern =====
PHPは昔privateがなかったので、そういう古いコードとの一貫性の維持が目的なら、先頭_もあり。
[https://gihyo.jp/dev/serial/01/ruby/0014 第14回 DataMapperの使い方 | gihyo.jp]
 
===== 配列の要素数 =====
https://chatgpt.com/c/67ecd6ff-b06c-800b-8f44-cfeb9c5768bb
 
配列の要素数、長さを変数に格納して使うことがけっこうある。その際の変数名。
 
オブジェクト指向に従うなら、配列名_size/countの接尾辞がいい。
 
C++のvectorなどのコンテナーだと.size()でとれる。変数に格納せずにsizeでいい。
 
変数にあえて代入するならば、配列名_sizeが自然。
 
ただ、PHPだと、countで要素数を取得する。その都合で、_countがよい。
item_list = [];
item_list_size
item_list_count
 
==== OOP ====
 
===== 継承とtrait =====
https://chatgpt.com/c/67cea053-9f50-800b-b22f-67aea7ac0dfe
 
apcとstaticのキャッシュクラスがあって、それとは別にビジネスロジックの共通化をしたい場合、いくつか方法がある。
 
# apc と static を統合した親クラスで trait を use し、子クラスで継承する
# apc と static を子クラスで直接継承し、trait を use
# 継承(extends)ではなく、キャッシュクラスを別のクラスとして利用する という考え方です。
 
===== 依存注入(DI)・継承・trait の使い分けまとめ =====
https://chatgpt.com/c/67cea053-9f50-800b-b22f-67aea7ac0dfe
 
キャッシュやORMのような、切り替え可能な機能の場合、DIで実装してプロパティーに格納して使うのが使いやすい。DIはテストのしやすさに勝る。
 
継承は親子関係が明確な場合。
 
===== コンストラクターのアクセス権 =====
基本はpublicだが、privateとprotectedを指定する場面がある。デザインパターンと関係している。
 
https://chatgpt.com/c/67fdac9a-2fac-800b-91bf-460c10fd72f5
 
* protected: 継承先のみ。ベースクラスや抽象クラスで使用する。ベースクラスや抽象クラスは継承を前提とするから、直接インスタンス生成してほしくないから。ファクトリーパターンと組み合わせる。
* private: クラス内部のみ。シングルトン・ユーティリティー (静的ファクトリーメソッド専用クラス) 系クラスで、インスタンスを作って欲しくない、1個だけのように、インスタンスの生成数を制限したい場合。
 
==== DB ====
[http://blog.tojiru.net/article/277021312.html PDOの真の力を開放する - PHPでデータベースを扱う(3): Architect Note]
 
DBアクセスのモデル化。行をクラスとすると扱いやすい模様。
 
getterを作ったり、データの妥当性のチェックなどもできる。
 
select/insert/などはmapperでクラスとDB列名を対応付けて処理する。自前で実装する場合はこういうつくりがいいらしい。
 
データベース関係のデザインパターンがいくつかある。
 
* Active Record
* Data Mapper
 
===== Active Record pattern =====
 
* [https://ja.wikipedia.org/wiki/Active_Record Active Record - Wikipedia]
* [https://www.techscore.com/tech/Ruby/Rails/other/designpattern/ デザインパターンから見たActive Record | TECHSCORE(テックスコア)]
 
テーブルレコードに対応するクラスを用意して、そのクラス自体にDB操作もさせる。
 
シンプルだが、複雑な操作が苦手。
 
エンティティーがテーブルと密接なため、例えばテーブル構造が変わった場合に大量に修正必要。
 
Ruby on Rails/Laravel+Eloquentなどで採用。
 
===== Data Mapper pattern =====
[https://gihyo.jp/dev/serial/01/ruby/0014 第14回 DataMapperの使い方 | gihyo.jp]
 
テーブルのレコードをクラスにするのはARと共通。
 
ただし、DB操作用のクラスを用意してそちらでDB操作する。
 
その都合、1テーブルに2クラス必要。
 
User/UserMapperのような対応関係。
 
2クラス必要だが、テーブル構造が変わった場合でも基本はMapperで吸収できる。
 
===== JOIN =====
Active RecordもData MapperもJOIN時の扱いが一番重要。単一エンティティーしか扱わないならどちらも同じ。
 
基本はエンティティーのプロパティーに持たせる感じ。
 
<blockquote>datamapperパターンでjoinする場合、エンティティーの扱いはどうなるの?
 
`DataMapper`パターンで`JOIN`を行う場合、エンティティの扱いは設計次第ですが、いくつかの注意点があります。`DataMapper`パターンは、データベースのテーブルとエンティティの間にマッピングを行い、エンティティはドメインロジックを持ち、データベースアクセスの責務を持たないことが特徴です。そのため、`JOIN`の処理をどの層で行うかを慎重に設計する必要があります。
 
以下、`JOIN`を行う際のエンティティの扱いと実装方法について解説します。
 
### 1. マッパークラスでの`JOIN`実装
 
`JOIN`を伴う複雑なクエリが必要な場合、マッパーが直接`JOIN`を使って複数テーブルを組み合わせた結果を取得し、それを複数のエンティティとしてマッピングする方法があります。例えば、ユーザーと注文を持つシステムで、ユーザーとその注文を一緒に取得したい場合、`UserMapper`で`JOIN`を行い、結果セットを`User`と`Order`エンティティに分割してマッピングします。
 
```python
 
class UserMapper:
 
    def find_user_with_orders(self, user_id):
 
        sql = """
 
            SELECT * FROM users
 
            JOIN orders ON users.id = orders.user_id
 
            WHERE users.id = %s
 
        """
 
        results = self.db.execute(sql, (user_id,))
 
       
 
        user = User(results[0]['user_id'], results[0]['user_name'])
 
        orders = [Order(row['order_id'], row['product_name'], user) for row in results]
 
        user.orders = orders
 
        return user
 
```
 
この方法では、1つのSQLクエリで必要なデータをすべて取得し、エンティティのプロパティにそれぞれのデータを設定します。
 
### 2. リポジトリでの集約
 
`JOIN`を使わず、各エンティティを個別に取得した後、リポジトリが集約の役割を担う方法もあります。リポジトリが各エンティティの`Mapper`を呼び出し、必要なエンティティ同士を関連付けることで`JOIN`を再現します。例えば、まず`UserMapper`でユーザー情報を取得し、次に`OrderMapper`で該当ユーザーの注文を取得してエンティティ間で関連付けます。
 
```python
 
class UserRepository:
 
    def __init__(self, user_mapper, order_mapper):
 
        self.user_mapper = user_mapper


テーブルのレコードをクラスにするのはARと共通。
        self.order_mapper = order_mapper


ただし、DB操作用のクラスを用意してそちらでDB操作する。
    def get_user_with_orders(self, user_id):


その都合、1テーブルに2クラス必要。
        user = self.user_mapper.find(user_id)


User/UserMapperのような対応関係。
        orders = self.order_mapper.find_by_user_id(user_id)


2クラス必要だが、テーブル構造が変わった場合でも基本はMapperで吸収できる。
        user.orders = orders


===== JOIN =====
        return user
Active RecordもData MapperもJOIN時の扱いが一番重要。単一エンティティーしか扱わないならどちらも同じ。


基本はエンティティーのプロパティーに持たせる感じ。
```</blockquote>UserテーブルとOrderテーブルがあって、あるユーザーの注文一覧を取得したい場合を考える。


<blockquote>datamapperパターンでjoinする場合、エンティティーの扱いはどうなるの?
結局、user.ordersみたいな感じで、エンティティーに外部テーブルのレコードを配列で持たせるつくりになる。


`DataMapper`パターンで`JOIN`を行う場合、エンティティの扱いは設計次第ですが、いくつかの注意点があります。`DataMapper`パターンは、データベースのテーブルとエンティティの間にマッピングを行い、エンティティはドメインロジックを持ち、データベースアクセスの責務を持たないことが特徴です。そのため、`JOIN`の処理をどの層で行うかを慎重に設計する必要があります。
クロス集計する場合は、users[0].orderみたいな感じ。メインのエンティティーのプロパティーに持たせる。フラットじゃないのでちょっと気持ち悪い。が、まあ構造としてこうなるのは順当。


以下、`JOIN`を行う際のエンティティの扱いと実装方法について解説します。
方法として、1回のSQLで取得するか、それぞれのエンティティーを取得してマージするか。1回のSQLでやったほうが当然いい。


### 1. マッパークラスでの`JOIN`実装
==== Other ====


`JOIN`を伴う複雑なクエリが必要な場合、マッパーが直接`JOIN`を使って複数テーブルを組み合わせた結果を取得し、それを複数のエンティティとしてマッピングする方法があります。例えば、ユーザーと注文を持つシステムで、ユーザーとその注文を一緒に取得したい場合、`UserMapper`で`JOIN`を行い、結果セットを`User`と`Order`エンティティに分割してマッピングします。
===== 1対1-多対多 =====
プログラミング言語でデータの関連付けをすることがある。


```python
1対1の場合、配列、連想配列のキーバリュー形式のデータがぴったり。


class UserMapper:
多対多の場合。これも配列。二次元配列で基本は0要素目など。
$array[][]


    def find_user_with_orders(self, user_id):
==== Project ====


        sql = """
===== レガシープロジェクトの立て直し =====
https://chatgpt.com/c/67481a93-adc0-800b-81c4-20d763133002


            SELECT * FROM users
1. 現状分析


            JOIN orders ON users.id = orders.user_id
(1) ソフトウェアの動作確認


            WHERE users.id = %s
現在の環境でアプリケーションを動作させる。


        """
どの部分が機能していて、どこが問題かを確認する。


        results = self.db.execute(sql, (user_id,))
必要であればエラーログを確認する。


       
(2) 依存関係の調査


        user = User(results[0]['user_id'], results[0]['user_name'])
アプリケーションのライブラリやフレームワークのバージョンを調査。


        orders = [Order(row['order_id'], row['product_name'], user) for row in results]
サポートが終了しているもの、互換性が失われたものを特定。


        user.orders = orders
(3) コードベースの状態評価


        return user
コードの品質 (可読性、設計、テストカバレッジ) を確認。


```
セキュリティリスクを特定する (例えば、脆弱性が放置されていないか)。


この方法では、1つのSQLクエリで必要なデータをすべて取得し、エンティティのプロパティにそれぞれのデータを設定します。
2. 計画立案


### 2. リポジトリでの集約
(1) ゴール設定


`JOIN`を使わず、各エンティティを個別に取得した後、リポジトリが集約の役割を担う方法もあります。リポジトリが各エンティティの`Mapper`を呼び出し、必要なエンティティ同士を関連付けることで`JOIN`を再現します。例えば、まず`UserMapper`でユーザー情報を取得し、次に`OrderMapper`で該当ユーザーの注文を取得してエンティティ間で関連付けます。
具体的な目標を設定 (例: パフォーマンス改善、保守性向上、セキュリティ強化)。


```python
(2) 優先順位の決定


class UserRepository:
どの機能を維持し、どの機能を削除または置き換えるか決定。


    def __init__(self, user_mapper, order_mapper):
ユーザーに直接影響を与える部分を優先。


        self.user_mapper = user_mapper
(3) リスク評価とバックアップ


        self.order_mapper = order_mapper
修正に伴うリスクを評価し、現行システムのバックアップを取得。


    def get_user_with_orders(self, user_id):
3. 環境整備


        user = self.user_mapper.find(user_id)
(1) 開発環境のモダナイズ


        orders = self.order_mapper.find_by_user_id(user_id)
ローカル環境やコンテナ (Docker) を用意してテストを容易にする。


        user.orders = orders
CI/CD パイプラインの整備。


        return user
(2) 依存関係の更新


```</blockquote>UserテーブルとOrderテーブルがあって、あるユーザーの注文一覧を取得したい場合を考える。
サポートされていないライブラリやフレームワークをアップグレードまたは置き換える。


結局、user.ordersみたいな感じで、エンティティーに外部テーブルのレコードを配列で持たせるつくりになる。
(3) セキュリティの確保


クロス集計する場合は、users[0].orderみたいな感じ。メインのエンティティーのプロパティーに持たせる。フラットじゃないのでちょっと気持ち悪い。が、まあ構造としてこうなるのは順当。
古いOSSの脆弱性を修正。


方法として、1回のSQLで取得するか、それぞれのエンティティーを取得してマージするか。1回のSQLでやったほうが当然いい。
HTTPSの導入、認証強化、インプット検証など。


==== Other ====
4. コードのモダナイズ


===== 1対1-多対多 =====
(1) リファクタリング
プログラミング言語でデータの関連付けをすることがある。


1対1の場合、配列、連想配列のキーバリュー形式のデータがぴったり。
レガシーコードをよりモダンで可読性の高いコードに変換。


多対多の場合。これも配列。二次元配列で基本は0要素目など。
デザインパターンを適用して保守性を向上。
$array[][]


==== Project ====
(2) テストの追加


===== レガシープロジェクトの立て直し =====
ユニットテスト、統合テストを導入。
https://chatgpt.com/c/67481a93-adc0-800b-81c4-20d763133002


1. 現状分析
既存の機能が壊れないことを確認するための自動化されたテスト。


(1) ソフトウェアの動作確認
(3) フロントエンド/バックエンドの分離


現在の環境でアプリケーションを動作させる。
必要に応じてモノリシック構造を分離し、モダンなアーキテクチャ (SPA、Microservices など) に移行。


どの部分が機能していて、どこが問題かを確認する。
5. 機能拡張とデプロイ


必要であればエラーログを確認する。
(1) 新しい機能の追加


(2) 依存関係の調査
必要に応じて、現代のニーズに合った新機能を実装。


アプリケーションのライブラリやフレームワークのバージョンを調査。
(2) 運用環境でのテスト


サポートが終了しているもの、互換性が失われたものを特定。
新しい環境で徹底的にテストし、問題がないことを確認。


(3) コードベースの状態評価
(3) 本番環境にデプロイ


コードの品質 (可読性、設計、テストカバレッジ) を確認。
ロールバック計画を準備しつつ、安全にデプロイ。


セキュリティリスクを特定する (例えば、脆弱性が放置されていないか)。
6. 継続的改善


2. 計画立案
(1) モニタリングの導入


(1) ゴール設定
エラーログやパフォーマンスを監視し、迅速に対応できる仕組みを導入。


具体的な目標を設定 (例: パフォーマンス改善、保守性向上、セキュリティ強化)
(2) 定期的なアップデート


(2) 優先順位の決定
フレームワークやライブラリを継続的に更新し、レガシー化を防ぐ。


どの機能を維持し、どの機能を削除または置き換えるか決定。
(3) コミュニティへの貢献


ユーザーに直接影響を与える部分を優先。
OSSとしての性質を活かし、変更内容をコミュニティに共有することでフィードバックを得る。


(3) リスク評価とバックアップ
このプロセスを通じて、安定した動作を保ちながら徐々に近代化することが可能です。特に、「現状分析」と「環境整備」をしっかり行うことで、後続の作業がスムーズになります。


修正に伴うリスクを評価し、現行システムのバックアップを取得。
== AI ==


3. 環境整備
=== 対話AI ===


(1) 開発環境のモダナイズ
==== List ====
[https://notepm.jp/blog/24168 【2024年版】対話型AIサービスおすすめ11選を徹底比較!チャットボットとの違い・メリット・課題・選び方なども紹介 - NotePM]


ローカル環境やコンテナ (Docker) を用意してテストを容易にする。
いろいろある。
{| class="wikitable"
|+
!Name
!
!
!
|-
|Bing
|
|
|
|-
|Perplexity AI
|
|
|
|-
|ChatGPT
|
|
|
|-
|Google Gemini
|
|
|
|}


CI/CD パイプラインの整備。
==== ChatGPT ====


(2) 依存関係の更新
===== Plan =====
[https://openai.com/chatgpt/ ChatGPT | OpenAI]


サポートされていないライブラリやフレームワークをアップグレードまたは置き換える。
Free/Plusの2のプランがある。
 
{| class="wikitable"
(3) セキュリティの確保
|+
!
!Free
!Plus
|-
|金額 [USD/月]
|0
|20
|-
|機能
|基本
|アーリーアクセス
|-
|エンジン
|GPT-4o mini
|GPT-4/GPT-4o/GPT-4o mini
|-
|制限
| -
|GPT-4oの5倍以上のメッセージ送信
|-
|その他
| -
|データ分析、ファイルアップロード、ビジョン、Webブラウジング
|-
|画像生成
| -
|DALL-E
|}
送信可能なメッセージ数、エンジン、画像生成などが大きな違いだろう。


古いOSSの脆弱性を修正。
===== Account =====
公式サイトにアカウントの意味の説明がない。しかたないので、ChatGPTに質問。<blockquote>ChatGPTに会員登録する意味は何ですか?


HTTPSの導入、認証強化、インプット検証など。


4. コードのモダナイズ
ChatGPTに会員登録する主な利点はいくつかあります。


(1) リファクタリング
1. **パーソナライズされた体験**: 登録すると、あなたの好みや過去のやり取りに基づいて、よりカスタマイズされた応答が得られます。


レガシーコードをよりモダンで可読性の高いコードに変換。
2. **履歴の管理**: 過去のチャット履歴を保存し、いつでも見返すことができるため、情報の確認が簡単になります。


デザインパターンを適用して保守性を向上。
3. **新機能へのアクセス**: 登録ユーザーは新しい機能やアップデートを優先的に利用できる場合があります。


(2) テストの追加
4. **プレミアム機能**: 一部のサービスでは、会員登録をすることで、より高度な機能やサポートが提供されることがあります。


ユニットテスト、統合テストを導入。
5. **セキュリティとプライバシー**: アカウントを持つことで、データの管理やプライバシーの設定をより細かく調整できます。


既存の機能が壊れないことを確認するための自動化されたテスト。
興味があれば、ぜひ登録を検討してみてください!他に質問があればお知らせください。</blockquote>自分の過去の質問の履歴を見れるだけでも便利かも。


(3) フロントエンド/バックエンドの分離
===== 方法 =====


必要に応じてモノリシック構造を分離し、モダンなアーキテクチャ (SPA、Microservices など) に移行。
====== 質問の分割 ======
https://chatgpt.com/c/673bdc0d-e0e0-800b-a22b-4fa19e64476c


5. 機能拡張とデプロイ
Q. chatgptで質問するとき、連続して質問すると、同じURLで複数の質問が表示される。リロードして質問を分けたほうがいいのか?


(1) 新しい機能の追加
A. どちらでも問題ない。が、質問が関連しているなら同じチャットで継続したほうがいい。直前の質問も文脈を考慮できる。完全に話が異なるなら分けたほうが後で整理したり、URLを共有したときにわかりやすい。


必要に応じて、現代のニーズに合った新機能を実装。
===== 感想 =====


(2) 運用環境でのテスト
====== 2024-11-14 Thu ======
https://gnusocial.jp/notice/7806505<blockquote>[[/gnusocial.jp/group/32/id|!it]] [[/gnusocial.jp/group/28/id|!ai]] 業務でPHPの開発作業をしていて、ChatGPTを使いだして便利に感じています。検索エンジンの代わりに使っています。


新しい環境で徹底的にテストし、問題がないことを確認。
例えば、「laravel eloquentでリレーション先のテーブルの主キー名の取得方法は?」と質問します。


(3) 本番環境にデプロイ
[[/chatgpt.com/c/67354314-fbdc-800b-a4e4-65f96d1a8fb2|https://chatgpt.com/c/67354314-fbdc-800b-a4e4-65f96d1a8fb2]]


ロールバック計画を準備しつつ、安全にデプロイ。
getRelatedというややマニアックなメソッドを教えてくれます[eloquent getrelated] で検索してもなかなかたどり着けないです。


6. 継続的改善
こういう検索エンジンで検索しにくい質問で便利だなと思います。


(1) モニタリングの導入
検索エンジンで検索すると、的外れな情報も大量にヒットします。対話AIはそのごみの混ざった検索結果を分析した結果をコンパクトに返してくれます。対話AI使わなくても、検索エンジンで時間かければわかりますが、大幅に時間短縮できます。


エラーログやパフォーマンスを監視し、迅速に対応できる仕組みを導入。
大量の凡人健常者が取り組んだ方法論として決まりきったものは、記憶の問題、ただの神経衰弱です。こういうのを検索エンジンの改良版としてAIに任せるのはいい使い方だと思います。


(2) 定期的なアップデート
個人的に、ただの知識、事実は重要度高くないと思いますが、一般社会では評価する側の頭が悪いので、これが重宝されます。
 
同僚や先輩に聞くより対話AIのほうがよほど頭いいです。話すことないです。聞くほうが時間の無駄なので。凡人はどんどん要らなくなります。
 
一方、私みたいなキチガイのデータは少ないので、検索エンジンやAIに聞いても出てこないです。世界で自分だけのオリジナルに専念するのがたぶんいいです。</blockquote>
 
====== 2024-11-19 Tue ======
https://gnusocial.jp/notice/7867350<blockquote>[[/gnusocial.jp/group/28/id|!ai]] ChatGPTが検索エンジンの改良版としてやっぱり便利。さっきこういう質問しました。
 
phpのメソッド名で、英単語の修飾語は前と後ろどちらがいい?例えば、namePrefixed()とprefixedName()のどちらがいい? [[/chatgpt.com/c/673bd358-3dc8-800b-8ec9-d745cc0eba85|https://chatgpt.com/c/673bd358-3dc8-800b-8ec9-d745cc0eba85]]
 
私はこのレベルの細かい疑問がすぐ浮かぶのです。これを人間にきくと、頓珍漢な回答だったり、そもそも回答してもらえないし、何ならこういう質問した私がなぜかキチガイ扱いされて、微妙な雰囲気になって、質問できなくなって、ストレスが溜まって、居づらくなって早期退職になるんです。意味不明です。ただの質問にお気持ちの配慮とか面倒なので。


フレームワークやライブラリを継続的に更新し、レガシー化を防ぐ。
この間、 [[/misskey-square.net/users/9g2o6eycu3|@yuriha]] に突っ込まれた件も、たぶん対話AIとお互い会話したほうが有意義だったんじゃないかとすら思います。相手も私に突っ込む前に対話AIと会話したほうが自分の主張の自己矛盾、頓珍漢さに気づけたんじゃないかとすら思えます。私が突っ込んでまーた私がキチガイ扱いされるのも回避されます。対話AIからの客観的な指摘なら、同じ内容であっても、キチガイの私が言うより納得しやすいでしょう?同じ内容なら対話AIのほうが凡人健常者にとっては、信じ込みやすいでしょ?


(3) コミュニティへの貢献
対話AIだとお気持ちの配慮いらないし、当たり前ですけど、キチガイ扱いされることもないので、快適です。元々対話AIには懐疑的でしたが、どちらかというと私のようなキチガイが凡人健常者の知識を拝借するためにあるような印象を持ちます。


OSSとしての性質を活かし、変更内容をコミュニティに共有することでフィードバックを得る。
検索エンジンでも調べることはできますが、めちゃくちゃ時間かかるんです。自分で複数の意見をみつけて、頭の中で比較検討して整理するので。これを一瞬でやってくれるのが楽。途中のデータ整理、目視は単純作業に近いのです。他のことに頭使えます。


このプロセスを通じて、安定した動作を保ちながら徐々に近代化することが可能です。特に、「現状分析」と「環境整備」をしっかり行うことで、後続の作業がスムーズになります。
もはや技術とか、ただの暗記の神経衰弱は別にいらないです。一般企業の上長とか、士業のように、単純知識でマウント取るタイプの仕事はこれで確かに駆逐されます。どうせ対話AIのほうが賢いのだから。知識量で勝てるわけないです。全世界の情報の集積結果なんだから。


== AI ==
凡人健常者の知識を拝借して、世界でだれにも真似できないキチガイ部分に専念できます。GNU socialの開発もこれでいけると思います。</blockquote>


=== 対話AI ===
== Shell ==


==== List ====
=== Shell Command Language ===
[https://notepm.jp/blog/24168 【2024年版】対話型AIサービスおすすめ11選を徹底比較!チャットボットとの違い・メリット・課題・選び方なども紹介 - NotePM]


いろいろある。
==== Compound Commands ====
{| class="wikitable"
[https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/utilities/V3_chap02.html#tag_18_09_04 Shell Command Language]
|+
 
!Name
===== Case Conditional Construct =====
!
case word in
!
    [(]pattern1) compound-list;;
!
    [[(]pattern[ | pattern] ... ) compound-list;;] ...
|-
    [[(]pattern[ | pattern] ... ) compound-list]
|Bing
esac
|
|
|
|-
|Perplexity AI
|
|
|
|-
|ChatGPT
|
|
|
|-
|Google Gemini
|
|
|
|}


==== ChatGPT ====
* 未マッチで終了ステータス0。
* pattern部分: シェル展開が有効。他はglob。
* |でOR検索相当。
* 最後のパターンの;;は省略可能。if文のようにも使える。
* 全パターンの捕捉は最後に*。空でもマッチする。?は最低1文字必要。


===== Plan =====
BREでは未対応な|のORマッチに対応しているのが最大の特徴。文法なのでコマンドを実行せず早い。grepを使わずにできるだけこちらを使ったほうがいい。
[https://openai.com/chatgpt/ ChatGPT | OpenAI]


Free/Plusの2のプランがある。
=== ワイルドカード ===
{| class="wikitable"
ワイルドカードで.始まりのファイルをマッチさせたい。
|+
!
!Free
!Plus
|-
|金額 [USD/月]
|0
|20
|-
|機能
|基本
|アーリーアクセス
|-
|エンジン
|GPT-4o mini
|GPT-4/GPT-4o/GPT-4o mini
|-
|制限
| -
|GPT-4oの5倍以上のメッセージ送信
|-
|その他
| -
|データ分析、ファイルアップロード、ビジョン、Webブラウジング
|-
|画像生成
| -
|DALL-E
|}
送信可能なメッセージ数、エンジン、画像生成などが大きな違いだろう。


===== Account =====
以下ならマッチするが、ブレース展開 (brace expansion) はPOSIX shでは使えなかった気がする。
公式サイトにアカウントの意味の説明がない。しかたないので、ChatGPTに質問。<blockquote>ChatGPTに会員登録する意味は何ですか?
echo {.*,*}


=== BOM ===
[https://stackoverflow.com/questions/3127436/adding-bom-to-utf-8-files unicode - Adding BOM to UTF-8 files - Stack Overflow]


ChatGPTに会員登録する主な利点はいくつかあります。
ExcelでUTF-8ファイルを開けるように、UTF-8のBOMをファイルにつけたい。
printf '\xEF\xBB\xBF' > with_bom.txt
上記コードでBOMを最初に書き込んで、後は追記する。


1. **パーソナライズされた体験**: 登録すると、あなたの好みや過去のやり取りに基づいて、よりカスタマイズされた応答が得られます。
=== awk ===
[https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/ The Open Group Base Specifications Issue 7]


2. **履歴の管理**: 過去のチャット履歴を保存し、いつでも見返すことができるため、情報の確認が簡単になります。
==== 変数 ====


3. **新機能へのアクセス**: 登録ユーザーは新しい機能やアップデートを優先的に利用できる場合があります。
===== 特別 =====
* NF: 列数。列の全表示などで使う基本的で重要な変数。
* NR: 行番号。


4. **プレミアム機能**: 一部のサービスでは、会員登録をすることで、より高度な機能やサポートが提供されることがあります。
===== スコープ =====
[http://www.fukano.jp/study_of_awk/basic/basic08.htm 変数のスコープ]


5. **セキュリティとプライバシー**: アカウントを持つことで、データの管理やプライバシーの設定をより細かく調整できます。
関数の仮引数のみ、ローカル変数扱いで、それ以外はグローバル変数。


興味があれば、ぜひ登録を検討してみてください!他に質問があればお知らせください。</blockquote>自分の過去の質問の履歴を見れるだけでも便利かも。
==== 文/statement ====


===== 方法 =====
* actions
** if/else
** while/do...while/for
** break/continue
** delete
** next
** exit
* output
** print
** printf


====== 質問の分割 ======
==== 関数 ====
https://chatgpt.com/c/673bdc0d-e0e0-800b-a22b-4fa19e64476c


Q. chatgptで質問するとき、連続して質問すると、同じURLで複数の質問が表示される。リロードして質問を分けたほうがいいのか?
===== 組込関数 =====


A. どちらでも問題ない。が、質問が関連しているなら同じチャットで継続したほうがいい。直前の質問も文脈を考慮できる。完全に話が異なるなら分けたほうが後で整理したり、URLを共有したときにわかりやすい。
* Arithmetic
** atan2
** cos
** sin
** exp
** log
** sqrt
** int
** rand
** srand
* String
** gsub
** index
** length
** match
** split
** sprintf
** sub
** substr
** tolower
** toupper
* I/O
** close
** getline
** system


===== 感想 =====
print/printfは関数ではなく、statement/文扱い。


====== 2024-11-14 Thu ======
==== ヘッダー出力、列別最大長さ出力。 ====
https://gnusocial.jp/notice/7806505<blockquote>[[/gnusocial.jp/group/32/id|!it]] [[/gnusocial.jp/group/28/id|!ai]] 業務でPHPの開発作業をしていて、ChatGPTを使いだして便利に感じています。検索エンジンの代わりに使っています。
<nowiki>awk -F, '{if(NR==1) print $0} {for(i=1; i<=NF; ++i){if (line[i] < length($i)) line[i] = length($i)}} END {for (i=1; i<=NF; ++i) {printf line[i]","}}' data/101542.csv</nowiki>


例えば、「laravel eloquentでリレーション先のテーブルの主キー名の取得方法は?」と質問します。
==== CSV ====
[https://qiita.com/ko1nksm/items/19407c1c53cbbc50569a シェルスクリプトの実験のために作った POSIX 準拠 awk 実装の CSVパーサー (RFC4180対応) #ShellScript - Qiita]<syntaxhighlight lang="awk" line="1">
# csvparser.awk


[[/chatgpt.com/c/67354314-fbdc-800b-a4e4-65f96d1a8fb2|https://chatgpt.com/c/67354314-fbdc-800b-a4e4-65f96d1a8fb2]]
## Usage
# awk -f csvparser.awk data.csv


getRelatedというややマニアックなメソッドを教えてくれます[eloquent getrelated] で検索してもなかなかたどり着けないです。
# CSV の論理的な一行毎に呼び出されるコールバック関数(サンプル)
# row: 行番号(最初の行は1) len: フィールド数 fields: フィールドデータ
function callback(row, len, fields,  col, field) {
    for ( col = 1; col <= len; col++ ) {
        field = fields[col]
        gsub(/\\/, "&&", field)  # \ は \\ にエスケープする
        gsub(/\n/, "\\n", field) # 改行は \n にエスケープする
        print row ":" col " " field
    }
}


こういう検索エンジンで検索しにくい質問で便利だなと思います。
BEGIN { row = max_idx = 0 }
 
{
検索エンジンで検索すると、的外れな情報も大量にヒットします。対話AIはそのごみの混ざった検索結果を分析した結果をコンパクトに返してくれます。対話AI使わなくても、検索エンジンで時間かければわかりますが、大幅に時間短縮できます。
    idx = 0
 
    sub(/\r$/, "")
大量の凡人健常者が取り組んだ方法論として決まりきったものは、記憶の問題、ただの神経衰弱です。こういうのを検索エンジンの改良版としてAIに任せるのはいい使い方だと思います。
    while ($0 != "") {
 
        if (match($0, /^(["]([^"]|["]["])*["]|[^,"]*)(,|$)/)) {
個人的に、ただの知識、事実は重要度高くないと思いますが、一般社会では評価する側の頭が悪いので、これが重宝されます。
            fields[++idx] = ""
 
        } else if (match($0, /^["]/)) {
同僚や先輩に聞くより対話AIのほうがよほど頭いいです。話すことないです。聞くほうが時間の無駄なので。凡人はどんどん要らなくなります。
            fields[++idx] = substr($0, 2)
 
            for (;;) {
一方、私みたいなキチガイのデータは少ないので、検索エンジンやAIに聞いても出てこないです。世界で自分だけのオリジナルに専念するのがたぶんいいです。</blockquote>
                if (getline == 0) exit 1
 
                sub(/\r$/, "")
====== 2024-11-19 Tue ======
                if (match($0, /^([^"]|["]["])*["](,|$)/)) break
https://gnusocial.jp/notice/7867350<blockquote>[[/gnusocial.jp/group/28/id|!ai]] ChatGPTが検索エンジンの改良版としてやっぱり便利。さっきこういう質問しました。
                gsub(/["]["]/, "\"")
                fields[idx] = fields[idx] "\n" $0
            }
            fields[idx] = fields[idx] "\n"
        } else {
            exit 1
        }
        field = substr($0, RSTART, RLENGTH)
        $0 = substr($0, RSTART + RLENGTH)
        lastcomma = sub(/,$/, "", field) > 0
        gsub(/^["]|["]$/, "", field) && gsub(/["]["]/, "\"", field)
        fields[idx] = fields[idx] field
    }
    if (lastcomma) fields[++idx] = ""
    while (idx < max_idx) delete fields[max_idx--]
    callback(++row, idx, fields)
    max_idx = idx
}


phpのメソッド名で、英単語の修飾語は前と後ろどちらがいい?例えば、namePrefixed()とprefixedName()のどちらがいい? [[/chatgpt.com/c/673bd358-3dc8-800b-8ec9-d745cc0eba85|https://chatgpt.com/c/673bd358-3dc8-800b-8ec9-d745cc0eba85]]
</syntaxhighlight>awkのCSVパーサー。先頭のBOMはあると認識できないので、tail -c +4でBOMを除外して使う。
tail -c +4 data/101543.csv | awk -f csvparser.awk


私はこのレベルの細かい疑問がすぐ浮かぶのです。これを人間にきくと、頓珍漢な回答だったり、そもそも回答してもらえないし、何ならこういう質問した私がなぜかキチガイ扱いされて、微妙な雰囲気になって、質問できなくなって、ストレスが溜まって、居づらくなって早期退職になるんです。意味不明です。ただの質問にお気持ちの配慮とか面倒なので。
=== Other ===


この間、 [[/misskey-square.net/users/9g2o6eycu3|@yuriha]] に突っ込まれた件も、たぶん対話AIとお互い会話したほうが有意義だったんじゃないかとすら思います。相手も私に突っ込む前に対話AIと会話したほうが自分の主張の自己矛盾、頓珍漢さに気づけたんじゃないかとすら思えます。私が突っ込んでまーた私がキチガイ扱いされるのも回避されます。対話AIからの客観的な指摘なら、同じ内容であっても、キチガイの私が言うより納得しやすいでしょう?同じ内容なら対話AIのほうが凡人健常者にとっては、信じ込みやすいでしょ?
==== binary ====
[https://qiita.com/ko1nksm/items/dc8f247cdc5b7b58b736 POSIX準拠のシェルスクリプトでバイナリデータを扱う #Bash - Qiita]


対話AIだとお気持ちの配慮いらないし、当たり前ですけど、キチガイ扱いされることもないので、快適です。元々対話AIには懐疑的でしたが、どちらかというと私のようなキチガイが凡人健常者の知識を拝借するためにあるような印象を持ちます。
バイナリーデータの読込はodコマンド。なければhexdump。


検索エンジンでも調べることはできますが、めちゃくちゃ時間かかるんです。自分で複数の意見をみつけて、頭の中で比較検討して整理するので。これを一瞬でやってくれるのが楽。途中のデータ整理、目視は単純作業に近いのです。他のことに頭使えます。
書込はprintf。


もはや技術とか、ただの暗記の神経衰弱は別にいらないです。一般企業の上長とか、士業のように、単純知識でマウント取るタイプの仕事はこれで確かに駆逐されます。どうせ対話AIのほうが賢いのだから。知識量で勝てるわけないです。全世界の情報の集積結果なんだから。
head/tailの-cはPOSIXで使えたか?


凡人健常者の知識を拝借して、世界でだれにも真似できないキチガイ部分に専念できます。GNU socialの開発もこれでいけると思います。</blockquote>
==== root ====


== Shell ==
===== リダイレクト出力 =====
[https://blog.shaba.dev/posts/redirect-with-sudo sudo権限でリダイレクト処理を行ってファイルに書き込む方法]


=== Shell Command Language ===
リダイレクトはログインユーザーの権限でなされるらしく、root権限のある場所にファイル出力できない。


==== Compound Commands ====
teeコマンドでやる。
[https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/utilities/V3_chap02.html#tag_18_09_04 Shell Command Language]
pwd | sudo tee out.dat
teeコマンド実行する側でsudoが必要。


===== Case Conditional Construct =====
  case word in
==== ログインシェルの確認 ====
    [(]pattern1) compound-list;;
[https://docs.oracle.com/cd/E19683-01/816-3946/customize-89075/index.html 第 10 章 動作環境のカスタマイズ (Solaris ユーザ]
    [[(]pattern[ | pattern] ... ) compound-list;;] ...
ログインシェルはGUIログインでも内部的にある。ログインシェルが読みこむprofileファイルなどは、ログイン時に、1回だけ実行したい処理の記述場所として最適。
    [[(]pattern[ | pattern] ... ) compound-list]
SHELL環境変数にログインシェルのパスが入っている。
echo $SHELL
/bin/bash
==== OSの判別 ====
OSTYPE環境変数に値があるのでこれで判別する。
例えば以下の値が入っている。
linux-gnu
darwin23
これらを検知して判定する。
  case $OSTYPE in
  linux*) echo 'linux';;
  darwin*) echo 'Mac';;
  esac
  esac
==== Configure ====
===== profile =====
[https://blog1.mammb.com/entry/2019/12/01/090000 bash の初期化ファイル .profile, .bashrc, .bash_profile の使い分けと管理方針 - A Memorandum]
環境変数など~/.profileに全部のシェルの共通設定を記述して、~/.bash_profileなどのログインシェルやbashrcなどで参照するのがいい。


* 未マッチで終了ステータス0。
== cmd.exe ==
* pattern部分: シェル展開が有効。他はglob。
* |でOR検索相当。
* 最後のパターンの;;は省略可能。if文のようにも使える。
* 全パターンの捕捉は最後に*。空でもマッチする。?は最低1文字必要。


BREでは未対応な|のORマッチに対応しているのが最大の特徴。文法なのでコマンドを実行せず早い。grepを使わずにできるだけこちらを使ったほうがいい。
=== Control block ===


=== ワイルドカード ===
==== for ====
ワイルドカードで.始まりのファイルをマッチさせたい。
あくまでコマンド。


以下ならマッチするが、ブレース展開 (brace expansion) はPOSIX shでは使えなかった気がする。
===== nest =====
echo {.*,*}


=== BOM ===
* [https://chicagopile1-75.hatenablog.com/entry/2018/05/23/143502 バッチファイルで2重ループ - ハムスターに飼われる院生のブログ]
[https://stackoverflow.com/questions/3127436/adding-bom-to-utf-8-files unicode - Adding BOM to UTF-8 files - Stack Overflow]


ExcelでUTF-8ファイルを開けるように、UTF-8のBOMをファイルにつけたい。
* [https://web.archive.org/web/20230602041631/https://jj-blues.com/cms/wantto-useloop/ web.archive.org/web/20230602041631/https://jj-blues.com/cms/wantto-useloop/]
printf '\xEF\xBB\xBF' > with_bom.txt
上記コードでBOMを最初に書き込んで、後は追記する。


=== awk ===
ネストはできない。二重ループしたければ、関数にしてそれを呼び出す。
[https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/ The Open Group Base Specifications Issue 7]


==== 変数 ====
=== bitsadmin ===
Windowsでのファイルダウンロードコマンド


===== 特別 =====
Windows 7以降ではbitsadminコマンドがあり、これがwget相当となる。
* NF: 列数。列の全表示などで使う基本的で重要な変数。
* NR: 行番号。


===== スコープ =====
書式:
[http://www.fukano.jp/study_of_awk/basic/basic08.htm 変数のスコープ]
bitsadmin /transfer <job name> <URL> <output path>
<job name>と<output path>は必須なので注意する。


関数の仮引数のみ、ローカル変数扱いで、それ以外はグローバル変数。
=== certutil ===
Windowsでのハッシュの確認に使える。
certutil -hashfile file


==== 文/statement ====
SHA1 ハッシュ (対象 C:\moconavi\windows\Moconavi\ext\chromium\moconavium.exe):
e0da85b04b6970ac1f0c33db7a9ad607fdbd44eb
CertUtil: -hashfile コマンドは正常に完了しました。


* actions
=== rlogin.cmd ===
** if/else
コマンドキーの送信を自動化できる?
** while/do...while/for
rem rlogin.cmd
** break/continue
** delete
@Echo off
** next
Set SERVER=192.168.0.0
** exit
Set USERNAME=
* output
Set PASSWORD=
** print
** printf
Cmdkey /generic:TERMSRV/%SERVER% /user:%USERNAME% /pass:%PASSWORD%
Start mstsc /v:%SERVER%
Timeout 5
Cmdkey /delete:TERMSRV/%SERVER%
 
=== 実行中プロセスのパスの確認 ===
出典: [https://superuser.com/questions/768984/show-exe-file-path-of-running-processes-on-the-command-line-in-windows Show EXE file path of running processes on the command-line in Windows - Super User]。
wmic process get ProcessID,ExecutablePath
wmic process where "name='mysqld.exe'" get ProcessID, ExecutablePath
wmic process where "name='mysqld.exe'" get ProcessID, ExecutablePath /FORMAT:LIST
 
=== 簡易編集モード/挿入モード ===


==== 関数 ====
* [https://softantenna.com/blog/windows-10-command-prompt-no-stop/ 【Tips】Windows 10のコマンドプロンプトが意図せず止まってしまう問題を回避する方法 | ソフトアンテナ]
* [https://superuser.com/questions/419717/windows-command-prompt-freezing-randomly Windows command prompt freezing randomly - Super User]


===== 組込関数 =====
Windows 10のcmd.exeは [簡易編集モード] が有効になっており、コマンドプロンプトを左クリックすると、テキストの選択が始まる。テキスト選択中はコマンドの実行が止まる。長時間かかるコマンドの実行中に誤操作で止まると困るので、これは無効にしたほうがよい。


* Arithmetic
cmd.exeを起動-左上のアイコンをクリック-[規定値]/[プロパティ]-[オプション]-[□簡易編集モード] を選ぶ。
** atan2
 
** cos
そのほか、 <code>git log</code> のような制御が移るコマンドを実行してしばらくすると、操作できなくなる。
** sin
** exp
** log
** sqrt
** int
** rand
** srand
* String
** gsub
** index
** length
** match
** split
** sprintf
** sub
** substr
** tolower
** toupper
* I/O
** close
** getline
** system


print/printfは関数ではなく、statement/文扱い。
[□挿入モード] にすると回避できる模様。


==== ヘッダー出力、列別最大長さ出力。 ====
== Web ==
<nowiki>awk -F, '{if(NR==1) print $0} {for(i=1; i<=NF; ++i){if (line[i] < length($i)) line[i] = length($i)}} END {for (i=1; i<=NF; ++i) {printf line[i]","}}' data/101542.csv</nowiki>


==== CSV ====
=== URL ===
[https://qiita.com/ko1nksm/items/19407c1c53cbbc50569a シェルスクリプトの実験のために作った POSIX 準拠 awk 実装の CSVパーサー (RFC4180対応) #ShellScript - Qiita]<syntaxhighlight lang="awk" line="1">
# csvparser.awk


## Usage
==== クエリー配列 ====
# awk -f csvparser.awk data.csv


# CSV の論理的な一行毎に呼び出されるコールバック関数(サンプル)
* [https://shinkufencer.hateblo.jp/entry/2019/05/18/163912 クエリストリングで配列を表現をするケースをざっと調べる - コード日進月歩]
# row: 行番号(最初の行は1) len: フィールド数 fields: フィールドデータ
* [https://qiita.com/s4kd0R/items/8a11d88099008bb1e9dc PHPでクエリパラメータから配列を受け取る物語 #JavaScript - Qiita]
function callback(row, len, fields, col, field) {
* [https://www.php.net/http_build_query PHP: http_build_query - Manual]
    for ( col = 1; col <= len; col++ ) {
 
        field = fields[col]
やり方がいくつかある。
        gsub(/\\/, "&&", field)  # \ は \\ にエスケープする
 
        gsub(/\n/, "\\n", field) # 改行は \n にエスケープする
# CSV文字列で受取後分割: <nowiki>https://www.sakdor.net/test/?var=1,2,3</nowiki> explode(",",$_GET[var]);
        print row ":" col " " field
# 配列添字
    }
## http://www.sakdor.net/test/?var&#x5B;&#x5D;=1&var&#x5B;&#x5D;=2&var&#x5B;&#x5D;=3
}
## http://www.sakdor.net/test/?var&#x5B;a&#x5D;=1&var&#x5B;b&#x5D;=2&var&#x5B;c&#x5D;=3
## http:www.sakdor.net?var[0]=1&var[1]=2&var[2]=3
 
データが決まっているならcsvがシンプル。
 
==== CGI ====
https://chatgpt.com/c/67634332-a3b8-800b-87a2-e21bd21a1cfc


BEGIN { row = max_idx = 0 }
WordPressなどのWebアプリだとファイル拡張子が登場しない。これはいくつかの仕組みが組み合わさって実現されている。
{
    idx = 0
    sub(/\r$/, "")
    while ($0 != "") {
        if (match($0, /^(["]([^"]|["]["])*["]|[^,"]*)(,|$)/)) {
            fields[++idx] = ""
        } else if (match($0, /^["]/)) {
            fields[++idx] = substr($0, 2)
            for (;;) {
                if (getline == 0) exit 1
                sub(/\r$/, "")
                if (match($0, /^([^"]|["]["])*["](,|$)/)) break
                gsub(/["]["]/, "\"")
                fields[idx] = fields[idx] "\n" $0
            }
            fields[idx] = fields[idx] "\n"
        } else {
            exit 1
        }
        field = substr($0, RSTART, RLENGTH)
        $0 = substr($0, RSTART + RLENGTH)
        lastcomma = sub(/,$/, "", field) > 0
        gsub(/^["]|["]$/, "", field) && gsub(/["]["]/, "\"", field)
        fields[idx] = fields[idx] field
    }
    if (lastcomma) fields[++idx] = ""
    while (idx < max_idx) delete fields[max_idx--]
    callback(++row, idx, fields)
    max_idx = idx
}


</syntaxhighlight>awkのCSVパーサー。先頭のBOMはあると認識できないので、tail -c +4でBOMを除外して使う。
# '''パーマリンク設定''' によるクリーンなURL構造の生成。
tail -c +4 data/101543.csv | awk -f csvparser.awk
# '''.htaccess(Apache)''' や '''リライトルール''' によるURLの書き換えとルーティング。
# '''index.php''' を起点とする動的な処理。
# '''テンプレート階層''' に従って適切なPHPファイルを呼び出す。


=== Other ===
.htaccessでindex.phpにリダイレクトして、index.phpから全て処理している。これにより省略できている。


==== binary ====
同じ用に、アプリ側が対応していれば、index.fcgiに全部リダイレクトして、パスを解釈してくれるなら、/でのアクセスもできる気がする。
[https://qiita.com/ko1nksm/items/dc8f247cdc5b7b58b736 POSIX準拠のシェルスクリプトでバイナリデータを扱う #Bash - Qiita]


バイナリーデータの読込はodコマンド。なければhexdump。
[https://stackoverflow.com/questions/36405496/how-can-i-run-a-fastcgi-script-in-root-url-without-path apache - How can I run a FastCGI script in root url (/ - without path)? - Stack Overflow]


書込はprintf。
=== HTTP ===
[https://www.rfc-editor.org/rfc/rfc9110.html RFC 9110: HTTP Semantics]


head/tailの-cはPOSIXで使えたか?
==== Content-Disposition ====
[https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Content-Disposition Content-Disposition - HTTP | MDN]


==== root ====
[https://datatracker.ietf.org/doc/html/rfc6266 RFC 6266 - Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP)]
Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="filename.jpg"
filenameでファイル名を指定する。ここの値は二重引用符で囲む。スペースを含む場合に必須になる。


===== リダイレクト出力 =====
==== multipart/form-data ====
[https://blog.shaba.dev/posts/redirect-with-sudo sudo権限でリダイレクト処理を行ってファイルに書き込む方法]
rfc7578


リダイレクトはログインユーザーの権限でなされるらしく、root権限のある場所にファイル出力できない。
* [https://datatracker.ietf.org/doc/html/rfc7578 RFC 7578 - Returning Values from Forms: multipart/form-data]
* [https://qiita.com/sivertigo/items/14957200af5ad953d63b Multipart/form-dataの仕様メモ #HTTP - Qiita]


teeコマンドでやる。
ファイルアップロード用のMIME type。
pwd | sudo tee out.dat
teeコマンド実行する側でsudoが必要。


リクエストヘッダー
==== ログインシェルの確認 ====
Content-Type: multipart/form-data; boundary=--hogehoge
[https://docs.oracle.com/cd/E19683-01/816-3946/customize-89075/index.html 第 10 章 動作環境のカスタマイズ (Solaris ユーザ]
リクエストボディー
ログインシェルはGUIログインでも内部的にある。ログインシェルが読みこむprofileファイルなどは、ログイン時に、1回だけ実行したい処理の記述場所として最適。
--hogehoge
SHELL環境変数にログインシェルのパスが入っている。
  Content-Disposition: form-data; name="user_name"
  echo $SHELL
  Content-Type: text/plain
  /bin/bash
==== OSの判別 ====
test
OSTYPE環境変数に値があるのでこれで判別する。
--hogehoge
例えば以下の値が入っている。
  Content-Disposition: form-data; name="email"
  linux-gnu
   
  darwin23
sample@mail.com
これらを検知して判定する。
  --hogehoge
  case $OSTYPE in
Content-Disposition: form-data; name="gender"
  linux*) echo 'linux';;
  darwin*) echo 'Mac';;
  male
  esac
--hogehoge
==== Configure ====
Content-Disposition: form-data; name="user_profile" filename="image.jpeg"
===== profile =====
Content-Type: image/jpeg
[https://blog1.mammb.com/entry/2019/12/01/090000 bash の初期化ファイル .profile, .bashrc, .bash_profile の使い分けと管理方針 - A Memorandum]
環境変数など~/.profileに全部のシェルの共通設定を記述して、~/.bash_profileなどのログインシェルやbashrcなどで参照するのがいい。
\xff\xd8\....
--hogehoge--
ヘッダーでmultipart/form-dataを明記して、ボディーでデータを指定する。


== cmd.exe ==
[https://weblabo.oscasierra.net/curl-post/ curlコマンドでPOSTする, 様々な形式別メモ |]


=== Control block ===
curlでの送信理由。


==== for ====
-Fで送信データをname=data形式で指定する。ファイルの内容を指定する場合、@filenameで指定する。これを指定すると、リクエストボディーのfilename扱いにしてくれる模様。-Fを指定すると、-H 'Content-Type: multipart/form-data'が自動付与される。たぶん、-dと同様に-X POSTもつく。
あくまでコマンド。
curl -X POST -F file1=@/var/tmp/sample.jpg <nowiki>https://xxxxx.net/xxxxxx</nowiki>
データとテキストを同時送信したい場合、-Fで複数指定する。
curl -X POST -F 'age=30' -F file1=@/var/tmp/sample.jpg <nowiki>https://xxxxx.net/xxxxxx</nowiki>
curlだと上記のboundaryなどをうまくやってくれるのだと思う。


===== nest =====
リクエストボディー全体をファイルデータにする場合。
curl -X POST -H 'Content-Type: image/jpeg' --data-binary @/var/tmp/sample.jpg <nowiki>https://xxxxx.net/xxxxxx</nowiki>


* [https://chicagopile1-75.hatenablog.com/entry/2018/05/23/143502 バッチファイルで2重ループ - ハムスターに飼われる院生のブログ]
=== IP address ===
出典: [https://glocalnet.jp/vpn/topix/archives/67#:~:text=%EF%BC%94%EF%BC%8E%E5%9B%BA%E5%AE%9AIP%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%AE%E5%8F%96%E5%BE%97%E6%96%B9%E6%B3%95%20%E5%8F%96%E5%BE%97%E6%96%B9%E6%B3%95%E3%81%AF%E4%B8%BB%E3%81%AB3%E3%81%A4%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82,%E3%83%BB%E5%A5%91%E7%B4%84%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%83%97%E3%83%AD%E3%83%90%E3%82%A4%E3%83%80%E3%81%A7%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%81%97%E3%81%A6%E7%94%B3%E3%81%97%E8%BE%BC%E3%82%80%E6%96%B9%E6%B3%95%20%E3%83%BB%E5%9B%BA%E5%AE%9AIP%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%AB%E5%AF%BE%E5%BF%9C%E3%81%97%E3%81%A6%E3%81%84%E3%82%8BSIM%E3%82%92%E5%A5%91%E7%B4%84%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%20%E3%83%BBVPN%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%9F%E5%9B%BA%E5%AE%9AIP%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%AE%E6%8F%90%E4%BE%9B%E4%BC%9A%E7%A4%BE%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95 固定IPアドレスの取得方法 ~実は簡単!フリーランスの方も必見です~|VPN活用日記|トピックス|グローカルネットの快適VPN【公式】| 株式会社グローカルネット]
 
自宅サーバーを行う際、固定IPアドレスが必要になる。
 
取得方法がいくつかある。


* [https://web.archive.org/web/20230602041631/https://jj-blues.com/cms/wantto-useloop/ web.archive.org/web/20230602041631/https://jj-blues.com/cms/wantto-useloop/]
* 契約しているプロバイダでオプションとして申し込む方法
* 固定IPアドレスに対応しているSIMを契約する方法
* '''VPNを利用した固定IPアドレスの提供会社を利用する方法'''


ネストはできない。二重ループしたければ、関数にしてそれを呼び出す。
VPNの固定IPアドレスが安いらしい。ryoかsuwakoが解説していた気がする。


=== bitsadmin ===
=== Authentication ===
Windowsでのファイルダウンロードコマンド
認証方式がいくつかある。HTTPで定義される認証方式 (HTTP認証) が有名。


Windows 7以降ではbitsadminコマンドがあり、これがwget相当となる。
==== Basic認証 ====
出典: [https://ja.wikipedia.org/wiki/Basic%E8%AA%8D%E8%A8%BC Basic認証 - Wikipedia]。


書式:
Authorization HTTPヘッダーにBasicのあとに [username:password] をBASE64でエンコードして送信する認証方式。
  bitsadmin /transfer <job name> <URL> <output path>
  GET /private/index.html HTTP/1.1
<job name>と<output path>は必須なので注意する。
Host: example.com
Authorization: Basic cm9vdDpwYXNzd29yZA{{=}}{{=}}
盗聴や改ざんが簡単だが、シンプルという利点がある。


=== certutil ===
[https://dev.classmethod.jp/articles/delete-cache-for-basic-authentication/ Basic認証のキャッシュを削除する(ログアウトする) | DevelopersIO]
Windowsでのハッシュの確認に使える。
certutil -hashfile file


SHA1 ハッシュ (対象 C:\moconavi\windows\Moconavi\ext\chromium\moconavium.exe):
ログアウト時は、hoge@domainのようにパスワードを省略した任意のユーザー名でログインを試みて既存のログイン状況を上書きする模様。
e0da85b04b6970ac1f0c33db7a9ad607fdbd44eb
CertUtil: -hashfile コマンドは正常に完了しました。


=== rlogin.cmd ===
Digest認証も共通。
コマンドキーの送信を自動化できる?
rem rlogin.cmd
@Echo off
Set SERVER=192.168.0.0
Set USERNAME=
Set PASSWORD=
Cmdkey /generic:TERMSRV/%SERVER% /user:%USERNAME% /pass:%PASSWORD%
Start mstsc /v:%SERVER%
Timeout 5
Cmdkey /delete:TERMSRV/%SERVER%


=== 実行中プロセスのパスの確認 ===
==== Digest認証 ====
出典: [https://superuser.com/questions/768984/show-exe-file-path-of-running-processes-on-the-command-line-in-windows Show EXE file path of running processes on the command-line in Windows - Super User]
[https://qiita.com/Threen/items/409971705767e2f89fb2 Basic認証・Digest認証・Form認証をざっくり理解 #Security - Qiita]
wmic process get ProcessID,ExecutablePath
wmic process where "name='mysqld.exe'" get ProcessID, ExecutablePath
wmic process where "name='mysqld.exe'" get ProcessID, ExecutablePath /FORMAT:LIST


=== 簡易編集モード/挿入モード ===
HTTP標準の認証。Basic認証とほぼ同じ。ただし、パスワードをハッシュ化している。そのため、DBのパスワードが流出した場合に比較的安全。


* [https://softantenna.com/blog/windows-10-command-prompt-no-stop/ 【Tips】Windows 10のコマンドプロンプトが意図せず止まってしまう問題を回避する方法 | ソフトアンテナ]
==== OAuth ====
* [https://superuser.com/questions/419717/windows-command-prompt-freezing-randomly Windows command prompt freezing randomly - Super User]
Ref


Windows 10のcmd.exeは [簡易編集モード] が有効になっており、コマンドプロンプトを左クリックすると、テキストの選択が始まる。テキスト選択中はコマンドの実行が止まる。長時間かかるコマンドの実行中に誤操作で止まると困るので、これは無効にしたほうがよい。
* [https://ja.wikipedia.org/wiki/OAuth OAuth - Wikipedia]


cmd.exeを起動-左上のアイコンをクリック-[規定値]/[プロパティ]-[オプション]-[□簡易編集モード] を選ぶ。
OAuth (オーオース) 権限の認可のための標準。OAuth 2.0が最新の標準。


そのほか、 <code>git log</code> のような制御が移るコマンドを実行してしばらくすると、操作できなくなる。
以下が登場人物。


[□挿入モード] にすると回避できる模様。
* resource owner: あるサイトのユーザー。
* resource server: あるサイトのユーザーのデータの保有サーバー。
* clent: クライアントアプリ。リソースサーバーのデータを使用したい。
* authorization server: クライアントにサイトへのアクセスを認証するサーバー。アクセストークンを発行して行う。


== Web ==
アクセストークンが実質的なパスワードのようなものだが、resource serverのパスワードを直接渡していない点が重要な違い。パスワードを直接渡さないことで、機能別に権限を細かく利用可否を制御できる。


=== URL ===
処理の流れ。


==== クエリー配列 ====
# client->resource owner: Authorization Request。ここでユーザーが手操作でアクセスを承認する。
# client<-resource owner: Authorization Grant。
# client->authorization server: Authorization Grant。承認された情報でアクセストークンを要求。
# client<-authorization server: Access Token
# client->resource server: Access Token。アクセストークンでアクセス。
# client<-resource server: Access Token


* [https://shinkufencer.hateblo.jp/entry/2019/05/18/163912 クエリストリングで配列を表現をするケースをざっと調べる - コード日進月歩]
Consumer Key/Secret: アプリ識別用のID/PW。
* [https://qiita.com/s4kd0R/items/8a11d88099008bb1e9dc PHPでクエリパラメータから配列を受け取る物語 #JavaScript - Qiita]
* [https://www.php.net/http_build_query PHP: http_build_query - Manual]


やり方がいくつかある。
Access Token: サイトにアクセスするためのパスワード。


# CSV文字列で受取後分割: <nowiki>https://www.sakdor.net/test/?var=1,2,3</nowiki> explode(",",$_GET[var]);
=== API ===
# 配列添字
## http://www.sakdor.net/test/?var&#x5B;&#x5D;=1&var&#x5B;&#x5D;=2&var&#x5B;&#x5D;=3
## http://www.sakdor.net/test/?var&#x5B;a&#x5D;=1&var&#x5B;b&#x5D;=2&var&#x5B;c&#x5D;=3
## http:www.sakdor.net?var[0]=1&var[1]=2&var[2]=3


データが決まっているならcsvがシンプル。
==== 複数レコードの登録 ====
[https://buddypia.com/2021/11/14/%E8%A4%87%E6%95%B0%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89api%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E8%AA%BF%E3%81%B9%E3%81%A6%E3%81%BF%E3%81%9F%E8%A9%B1/ 複数レコードの登録・更新・削除のREST APIについて調べてみた話(+@ Graph API) - junode | 個人開発ブログ]


==== CGI ====
既存のAPIは単一リソースの処理しかないことが多い。JavaScriptなどで単一リソースを何回も呼べばいいというのはそうだけど、JavaScriptなしでは動作しない。一括処理用のAPIを作るしかなくないか?
https://chatgpt.com/c/67634332-a3b8-800b-87a2-e21bd21a1cfc


WordPressなどのWebアプリだとファイル拡張子が登場しない。これはいくつかの仕組みが組み合わさって実現されている。
[https://www.yamarkz.com/blog/rest-web-api-practice REST WebAPIのプラクティス | yamarkz.com]


# '''パーマリンク設定''' によるクリーンなURL構造の生成。
delete_bulkなどのような一括処理用のAPIを作るしかない。内部的には単一処理のAPIを作る感じだったとしても。
# '''.htaccess(Apache)''' や '''リライトルール''' によるURLの書き換えとルーティング。
# '''index.php''' を起点とする動的な処理。
# '''テンプレート階層''' に従って適切なPHPファイルを呼び出す。


.htaccessでindex.phpにリダイレクトして、index.phpから全て処理している。これにより省略できている。
==== パラメーター ====
[https://stackoverflow.com/questions/25385559/rest-api-best-practices-args-in-query-string-vs-in-request-body json - REST API Best practices: args in query string vs in request body - Stack Overflow]


同じ用に、アプリ側が対応していれば、index.fcgiに全部リダイレクトして、パスを解釈してくれるなら、/でのアクセスもできる気がする。
パラメーターの指定に3種類ある。


[https://stackoverflow.com/questions/36405496/how-can-i-run-a-fastcgi-script-in-root-url-without-path apache - How can I run a FastCGI script in root url (/ - without path)? - Stack Overflow]
# リクエストボディー
# クエリー
# パス
 
パスはIDなどを指定する場合だけわかりやすい。それ以外のオプションはクエリーのほうがいい。
 
ボディーは、通常サーバーのアップロード・ダウンロードデータとして使われる。クエリーはデータの指定に使う。


=== HTTP ===
この原則に従うとシンプルだろう。
[https://www.rfc-editor.org/rfc/rfc9110.html RFC 9110: HTTP Semantics]


==== Content-Disposition ====
* URIには長さの制限がある。
[https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Content-Disposition Content-Disposition - HTTP | MDN]
* ボディー
** 引数が非常に多い場合。
** 画像などバイナリーデータ。
** キー・値構造を持たない場合。
* クエリー文字列
** 引数を簡単に確認できる。
** 共通の引数の場合。


[https://datatracker.ietf.org/doc/html/rfc6266 RFC 6266 - Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP)]
==== 検索機能のGET/POST ====
Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="filename.jpg"
filenameでファイル名を指定する。ここの値は二重引用符で囲む。スペースを含む場合に必須になる。


==== multipart/form-data ====
* [https://stackoverflow.com/questions/20550514/post-or-get-in-a-search-form .net - POST or GET in a search form? - Stack Overflow]
rfc7578


* [https://datatracker.ietf.org/doc/html/rfc7578 RFC 7578 - Returning Values from Forms: multipart/form-data]
検索機能にGETとPOSTのどちらを使うか?という議論がある。
* [https://qiita.com/sivertigo/items/14957200af5ad953d63b Multipart/form-dataの仕様メモ #HTTP - Qiita]


ファイルアップロード用のMIME type。
データ登録するわけなじゃないのだから、GETがいいんじゃない?


リクエストヘッダー
POSTだと、JSONをそのまま送れるので、複雑なケースに対応できる。特に、配列の送信が重要。
Content-Type: multipart/form-data; boundary=--hogehoge
リクエストボディー
--hogehoge
Content-Disposition: form-data; name="user_name"
Content-Type: text/plain
test
--hogehoge
Content-Disposition: form-data; name="email"
sample@mail.com
--hogehoge
Content-Disposition: form-data; name="gender"
male
--hogehoge
Content-Disposition: form-data; name="user_profile" filename="image.jpeg"
Content-Type: image/jpeg
\xff\xd8\....
--hogehoge--
ヘッダーでmultipart/form-dataを明記して、ボディーでデータを指定する。


[https://weblabo.oscasierra.net/curl-post/ curlコマンドでPOSTする, 様々な形式別メモ |]
GETのほうが検索条件をブックマークにできたり、URLを共有できるので、基本は便利。


curlでの送信理由。
ただし、検索などのパラメーターが長くなる場合、使用できない。そもそも検索でそんなに長いパラメーターというのがまずいかもしれない。2000文字あれば十分という説がある。


-Fで送信データをname=data形式で指定する。ファイルの内容を指定する場合、@filenameで指定する。これを指定すると、リクエストボディーのfilename扱いにしてくれる模様。-Fを指定すると、-H 'Content-Type: multipart/form-data'が自動付与される。たぶん、-dと同様に-X POSTもつく。
==== レート制限対策 ====
curl -X POST -F file1=@/var/tmp/sample.jpg <nowiki>https://xxxxx.net/xxxxxx</nowiki>
データとテキストを同時送信したい場合、-Fで複数指定する。
curl -X POST -F 'age=30' -F file1=@/var/tmp/sample.jpg <nowiki>https://xxxxx.net/xxxxxx</nowiki>
curlだと上記のboundaryなどをうまくやってくれるのだと思う。


リクエストボディー全体をファイルデータにする場合。
* [https://pikodon.com/note/php/api-cache/ APIの利用制限対策 | Web開発ノート]
curl -X POST -H 'Content-Type: image/jpeg' --data-binary @/var/tmp/sample.jpg <nowiki>https://xxxxx.net/xxxxxx</nowiki>
* [https://keirinomikata.zendesk.com/hc/ja/articles/4404549985945-%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E6%95%B0%E3%81%AB%E3%82%88%E3%82%8B%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E5%88%B6%E9%99%90%E3%81%AE%E5%AF%BE%E7%AD%96%E6%96%B9%E6%B3%95 リクエスト数によるアクセス制限の対策方法 – 請求管理ロボ ヘルプ]


=== IP address ===
いろいろ方法がある。
出典: [https://glocalnet.jp/vpn/topix/archives/67#:~:text=%EF%BC%94%EF%BC%8E%E5%9B%BA%E5%AE%9AIP%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%AE%E5%8F%96%E5%BE%97%E6%96%B9%E6%B3%95%20%E5%8F%96%E5%BE%97%E6%96%B9%E6%B3%95%E3%81%AF%E4%B8%BB%E3%81%AB3%E3%81%A4%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82,%E3%83%BB%E5%A5%91%E7%B4%84%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%83%97%E3%83%AD%E3%83%90%E3%82%A4%E3%83%80%E3%81%A7%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%81%97%E3%81%A6%E7%94%B3%E3%81%97%E8%BE%BC%E3%82%80%E6%96%B9%E6%B3%95%20%E3%83%BB%E5%9B%BA%E5%AE%9AIP%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%AB%E5%AF%BE%E5%BF%9C%E3%81%97%E3%81%A6%E3%81%84%E3%82%8BSIM%E3%82%92%E5%A5%91%E7%B4%84%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%20%E3%83%BBVPN%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%9F%E5%9B%BA%E5%AE%9AIP%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%AE%E6%8F%90%E4%BE%9B%E4%BC%9A%E7%A4%BE%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95 固定IPアドレスの取得方法 ~実は簡単!フリーランスの方も必見です~|VPN活用日記|トピックス|グローカルネットの快適VPN【公式】| 株式会社グローカルネット]。


自宅サーバーを行う際、固定IPアドレスが必要になる。
* cronなどでデータをサーバー上 (DBなど) に定期保存して、保存データを表示させる。
* 配列を利用して、1回のリクエストでまとめて取得する。
* インターバルを設ける。
* HTTP 429/413を検知して、リトライする。


取得方法がいくつかある。
==== 指数関数的バックオフ ====


* 契約しているプロバイダでオプションとして申し込む方法
* [https://docs.link.getmoneytree.com/docs/faq-rate-limiting APIレート制限は何か、どのように対処するのか?]
* 固定IPアドレスに対応しているSIMを契約する方法
* [[wikipedia:Exponential_backoff|Exponential backoff - Wikipedia]]
* '''VPNを利用した固定IPアドレスの提供会社を利用する方法'''
* [https://cloud.google.com/memorystore/docs/redis/exponential-backoff?hl=ja 指数バックオフ  |  Memorystore for Redis  |  Google Cloud]
* [https://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/cloud-design-patterns/retry-backoff.html バックオフパターンで再試行 - AWS 規範ガイダンス]リトライ時は以下のアルゴリズムがいいらしい。
wait_interval = base * 2^n +/- jitter


VPNの固定IPアドレスが安いらしい。ryoかsuwakoが解説していた気がする。
* <code>wait_interval</code> は、API が HTTP 429 で応答した場合に、システムがリクエストを再試行するまでの時間となります。
* <code>base</code> は最初の間隔、つまり最初の再試行までの待ち時間です。この値には3000msを使用することをお勧めします。
* <code>n</code> は、現在の呼び出しの前にリクエストが通らなかった数です。複数のスレッドやプロセスを使用して並行してAPIを呼び出している場合、<code>n</code>の値は現在のスレッド/プロセスにスコープされます。この値は、現在のスレッド/プロセスが、最後に成功した応答から何回 429 "Too Many Requests" エラーに遭遇したかを表します。
* <code>jitter</code> は 0 から <code>base</code> の間の乱数です。これは、複数のスレッド/プロセスが全く同時にAPIを呼び出さないように、リクエストを少しずつ分散させるために使用されます。システムが待機するたびに、この乱数値を再計算し <code>wait_interval</code> の合計に加算するか減算するか、ランダムで選択してください。


=== Authentication ===
==== バックエンドとフロントエンドの分離 ====
認証方式がいくつかある。HTTPで定義される認証方式 (HTTP認証) が有名。
https://chatgpt.com/c/6747e923-6174-800b-8816-dd741721de45


==== Basic認証 ====
SPA (Single Page Application) やJAMStackの影響で、バックエンドはデータを返すだけで、画面描画はフロントエンドが全部するというのが最近の流行。
出典: [https://ja.wikipedia.org/wiki/Basic%E8%AA%8D%E8%A8%BC Basic認証 - Wikipedia]。


Authorization HTTPヘッダーにBasicのあとに [username:password] をBASE64でエンコードして送信する認証方式。
SSR (Server Side Rendering) とCSR (Client Side Rendering) の違い。フロントエンドの高度化や分業などが理由とのこと。
GET /private/index.html HTTP/1.1
Host: example.com
Authorization: Basic cm9vdDpwYXNzd29yZA{{=}}{{=}}
盗聴や改ざんが簡単だが、シンプルという利点がある。


[https://dev.classmethod.jp/articles/delete-cache-for-basic-authentication/ Basic認証のキャッシュを削除する(ログアウトする) | DevelopersIO]
SSRの利点。


ログアウト時は、hoge@domainのようにパスワードを省略した任意のユーザー名でログインを試みて既存のログイン状況を上書きする模様。
* SEO
* 初期表示。
* 匿名。


Digest認証も共通。
SSRの課題。


==== Digest認証 ====
* サーバー負荷: データとHTML作成を同時に行うから。
[https://qiita.com/Threen/items/409971705767e2f89fb2 Basic認証・Digest認証・Form認証をざっくり理解 #Security - Qiita]
* 分散困難:  


HTTP標準の認証。Basic認証とほぼ同じ。ただし、パスワードをハッシュ化している。そのため、DBのパスワードが流出した場合に比較的安全。
キャッシュの活用がポイントになるとのこと。


==== OAuth ====
=== Network ===
Ref


* [https://ja.wikipedia.org/wiki/OAuth OAuth - Wikipedia]
==== ssh ====


OAuth (オーオース) 権限の認可のための標準。OAuth 2.0が最新の標準。
===== ssh-addの自動登録 =====
ssh agentに秘密鍵の登録は以下のコマンド。
ssh-add <秘密鍵のpath>
ただし、上記コマンドは再起動すると登録が消えるので毎回必要。


以下が登場人物。
~/.ssh/configに以下の内容を記入しておくと、次回からkeychainから自動で読み込まれるらしい ([https://qiita.com/sonots/items/a6dec06f95fca4757d4a macOS で再起動しても ssh agent に秘密鍵を保持させ続ける二つの方法 #SSH - Qiita])。
Host *
  UseKeychain yes
  AddKeysToAgent yes
うまくいかなかった。


* resource owner: あるサイトのユーザー。
[https://aifan.jp/2022/01/25/ssh-add%E3%82%92pc%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B%E5%BA%A6%E3%81%AB%E8%87%AA%E5%8B%95%E7%9A%84%E3%81%AB%E5%AE%9F%E8%A1%8C%E3%81%95%E3%81%9B%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E8%A8%AD%E5%AE%9A/ ssh-addをPC起動する度に自動的に実行させるための設定 | AIFAN]
* resource server: あるサイトのユーザーのデータの保有サーバー。
* clent: クライアントアプリ。リソースサーバーのデータを使用したい。
* authorization server: クライアントにサイトへのアクセスを認証するサーバー。アクセストークンを発行して行う。


アクセストークンが実質的なパスワードのようなものだが、resource serverのパスワードを直接渡していない点が重要な違い。パスワードを直接渡さないことで、機能別に権限を細かく利用可否を制御できる。
id_rsaの場合はIdentityFileを省略できるが、それ以外は指定が必要な模様。
Host *
  UseKeychain yes
  AddKeysToAgent yes
  IdentityFile ~/.ssh/id_ed25519


処理の流れ。
===== ssh経由でのリダイレクト出力 =====
[https://superuser.com/questions/400714/how-to-remotely-write-to-a-file-using-ssh bash - How to remotely write to a file using SSH - Super User]


# client->resource owner: Authorization Request。ここでユーザーが手操作でアクセスを承認する。
ssh経由で標準入力内容からファイルをリダイレクトで作成したいことがある。
# client<-resource owner: Authorization Grant。
# client->authorization server: Authorization Grant。承認された情報でアクセストークンを要求。
# client<-authorization server: Access Token
# client->resource server: Access Token。アクセストークンでアクセス。
# client<-resource server: Access Token


Consumer Key/Secret: アプリ識別用のID/PW。
sshのコマンド部分を文字列にすればOK。
ssh user@remotehost -T "cat > /remotefile.txt" <<-EOT
Some text
EOT
-Tで擬似端末を無効にしている。
===== パスフレーズの省略 =====
* [https://zenn.dev/luvmini511/articles/65786667221313 SSH パスフレーズ 省略したい!~ config 設定するか Keychain 登録自動化するか ~]
* [https://madoverload.com/2022/04/29/mac-ssh-agent/ Macのssh-agent]
SSH多段接続時とgit cloneでSSH鍵参照時に、パスフレーズを要求される。毎回要求されるのが手間。これを省略する方法がある。
~/.ssh/configに以下の設定を記述する。
Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519
* AddKeysToAgent=yesにすると、ssh-agentの実行時に自動的に鍵を追加する。
* UseKeychain=macOS専用。OSのキーチェーンからパスフレーズの検索を試みる。
* IdentityFile=SSH秘密鍵の絶対パス。デフォルトは~/.ssh/id_rsa。
上記3点で自動入力を試みる。
macOSで行う分には上記だけでパスワードは聞かれない。これをリモートでもやりたいなら、ssh-agentに登録が必要。
ログイン時に1回実行してくれたらいいので、ログインシェルの設定の~/.bash_profileに以下を記述。
echo 'ssh-add --apple-use-keychain' >>~/.bash_profile
これで端末の起動時に鍵を自動登録してくれるので、リモートでもパスフレーズを要求されない。


Access Token: サイトにアクセスするためのパスワード。
===== ssh_config =====
[https://linux.die.net/man/5/ssh_config ssh_config(5): OpenSSH SSH client config files - Linux man page]


=== API ===
重要な設定・構文がある。


==== 複数レコードの登録 ====
====== TOKENS ======
[https://buddypia.com/2021/11/14/%E8%A4%87%E6%95%B0%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89api%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E8%AA%BF%E3%81%B9%E3%81%A6%E3%81%BF%E3%81%9F%E8%A9%B1/ 複数レコードの登録・更新・削除のREST APIについて調べてみた話(+@ Graph API) - junode | 個人開発ブログ]
macのman ssh_configに詳しい。


既存のAPIは単一リソースの処理しかないことが多い。JavaScriptなどで単一リソースを何回も呼べばいいというのはそうだけど、JavaScriptなしでは動作しない。一括処理用のAPIを作るしかなくないか?
使用可能な指令が限定されている。


[https://www.yamarkz.com/blog/rest-web-api-practice REST WebAPIのプラクティス | yamarkz.com]
HostName (Macのみ)


delete_bulkなどのような一括処理用のAPIを作るしかない。内部的には単一処理のAPIを作る感じだったとしても。
* %h=リモートホスト名。Hostの指定部。
* %p=リモートポート。


==== パラメーター ====
====== WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! ======
[https://stackoverflow.com/questions/25385559/rest-api-best-practices-args-in-query-string-vs-in-request-body json - REST API Best practices: args in query string vs in request body - Stack Overflow]


パラメーターの指定に3種類ある。
* [https://www.niandc.co.jp/tech/20150729_2464/ ssh接続をする際に「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」と出てつながらない|テクニカルブログ|日本情報通信株式会社]
* [https://qiita.com/hnw/items/0eeee62ce403b8d6a23c 「SSHホスト鍵が変わってるよ!」と怒られたときの対処 #SSH - Qiita]


# リクエストボディー
ssh example.comなどを実行すると、IPアドレスの振り直しなどで、ホストの公開鍵が変わっていた場合、中間者攻撃への対策として失敗する。
# クエリー
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# パス
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!    @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
SHA256:.
Please contact your system administrator.
Add correct host key in /Users/z.ken.senoo/.ssh/known_hosts to get rid of this message.
Offending RSA key in /Users/z.ken.senoo/.ssh/known_hosts:1
Host key for [example.com]:3023 has changed and you have requested strict checking.
Host key verification failed.
Connection closed by UNKNOWN port 65535
Connection closed by UNKNOWN port 65535


パスはIDなどを指定する場合だけわかりやすい。それ以外のオプションはクエリーのほうがいい。
$HOME/.ssh/known_hostsの該当行を削除すれば解決する。以下のコマンドでも対応してくれる。
ssh-keygen -R example.com
いや、うまくいかない。~/.ssh/known_hostsに以下の該当ドメインの除外設定が必要な模様。
@cert-authority example.com ssh-rsa
「[https://man.openbsd.org/sshd sshd(8) - OpenBSD manual pages]」に記載がある。<blockquote>The marker is optional, but if it is present then it must be one of “@cert-authority”, to indicate that the line contains a certification authority (CA) key, or “@revoked”, to indicate that the key contained on the line is revoked and must not ever be accepted. Only one marker should be used on a key line.


ボディーは、通常サーバーのアップロード・ダウンロードデータとして使われる。クエリーはデータの指定に使う。
...


この原則に従うとシンプルだろう。
When performing host authentication, authentication is accepted if any matching line has the proper key; either one that matches exactly or, if the server has presented a certificate for authentication, the key of the certification authority that signed the certificate. For a key to be trusted as a certification authority, it must use the “@cert-authority” marker described above.</blockquote>https://chatgpt.com/c/67f321e3-3b78-800b-b263-3e7169488367


* URIには長さの制限がある。
通常、known_hostsには、接続済みのホストの公開鍵を記録し、次回以降の接続時の確認に使う。ただ、この場合、IPアドレスが動的に変更する場合や、鍵が頻繁に変更される場合に、警告になる。この対策として、@cert-authorityで、同じ行のホスト鍵を署名したCA鍵を信頼する。これにより、同一のCAの複数ホストを一括で信頼する。
* ボディー
** 引数が非常に多い場合。
** 画像などバイナリーデータ。
** キー・値構造を持たない場合。
* クエリー文字列
** 引数を簡単に確認できる。
** 共通の引数の場合。


==== 検索機能のGET/POST ====
==== curl ====
HTTPの通信のコマンドラインでの確認でよく使う。


* [https://stackoverflow.com/questions/20550514/post-or-get-in-a-search-form .net - POST or GET in a search form? - Stack Overflow]
===== Basic =====
[https://curl.se/docs/tutorial.html curl - Tutorial]
* -X: メソッド指定
* -d/--data-urlencode: リクエストボディー (key=value)を指定。-X POSTも自動指定になる。
curl -H "Content-Type: application/json" -d '{"name":"佐藤", "mail":"sato@example.com"}' localhost:5000/api/v1/users
JSONで送信する場合、ヘッダー指定が必須。


検索機能にGETとPOSTのどちらを使うか?という議論がある。
<nowiki>*</nowiki>-F: multipart/formのform指定。
curl -F "coolfiles=@fil1.gif;type=image/gif,fil2.txt,fil3.html"
  <nowiki>http://www.example.com/postit.cgi</nowiki>
@でfilename相当の指定。;でmime typeも指定できる。


データ登録するわけなじゃないのだから、GETがいいんじゃない?
@/</;type=自体を送信したい場合、-Fではなく、--form-stringを指定する。


POSTだと、JSONをそのまま送れるので、複雑なケースに対応できる。特に、配列の送信が重要。
===== curl: (60) SSL certificate problem: self-signed certificate =====
Ref: [https://linuxfan.info/curl-insecure curlで「自己署名証明書」を受け入れるには【curl: (60) SSL certificate problem: self signed certificate】 | LFI].


GETのほうが検索条件をブックマークにできたり、URLを共有できるので、基本は便利。
--insecureオプションを指定すると、localhostなどでの自己署名証明書を許可する。


ただし、検索などのパラメーターが長くなる場合、使用できない。そもそも検索でそんなに長いパラメーターというのがまずいかもしれない。2000文字あれば十分という説がある。
===== curl: Failed writing body =====
[https://askubuntu.com/questions/1449492/right-after-piping-to-head-tail-curl-23-failure-writing-output-to-desti pipe - Right After piping to "head"/"tail": "curl: (23) Failure writing output to destination" - Ask Ubuntu]


==== レート制限対策 ====
以下のようにhead -n 1を指定するとcurlがエラーを出力する。
curl -H "Content-Type: application/json; charset=utf-8" -H "X-HD-apitoken:$TOKEN"        -d "{\"dbSchemaId\":$dbSchemaId, \"limit\":1, \"offset\":$offset}"        <nowiki>https://$DOMAIN/$ACCOUNT/api/csvexport/version/1.0</nowiki> | head -n 1


* [https://pikodon.com/note/php/api-cache/ APIの利用制限対策 | Web開発ノート]
curl: Failed writing body
* [https://keirinomikata.zendesk.com/hc/ja/articles/4404549985945-%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E6%95%B0%E3%81%AB%E3%82%88%E3%82%8B%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E5%88%B6%E9%99%90%E3%81%AE%E5%AF%BE%E7%AD%96%E6%96%B9%E6%B3%95 リクエスト数によるアクセス制限の対策方法 – 請求管理ロボ ヘルプ]
curlは標準出力に全部書き込めたかチェックしているようで、head -n 1で切り捨てたらcurlはエラーになる。


いろいろ方法がある。
対策は、curl -sで出力を抑制するとのこと。これで解決。


* cronなどでデータをサーバー上 (DBなど) に定期保存して、保存データを表示させる。
==== Teleport ====
* 配列を利用して、1回のリクエストでまとめて取得する。
* インターバルを設ける。
* HTTP 429/413を検知して、リトライする。


==== 指数関数的バックオフ ====
* [https://goteleport.com/docs/connect-your-client/teleport-connect/ Using Teleport Connect | Teleport Docs]
* [https://speakerdeck.com/gree_tech/greetechcon2023-session-a6 SSH から Teleport へ - Speaker Deck]


* [https://docs.link.getmoneytree.com/docs/faq-rate-limiting APIレート制限は何か、どのように対処するのか?]
踏み台サーバー (Jump server/Jump host) をよりよく管理するためのサーバーソフトウェア。
* [[wikipedia:Exponential_backoff|Exponential backoff - Wikipedia]]
* [https://cloud.google.com/memorystore/docs/redis/exponential-backoff?hl=ja 指数バックオフ  |  Memorystore for Redis  |  Google Cloud]
* [https://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/cloud-design-patterns/retry-backoff.html バックオフパターンで再試行 - AWS 規範ガイダンス]リトライ時は以下のアルゴリズムがいいらしい。
wait_interval = base * 2^n +/- jitter


* <code>wait_interval</code> は、API が HTTP 429 で応答した場合に、システムがリクエストを再試行するまでの時間となります。
アクセスログなどを一元管理できる。商用版とオープンソース版がある。
* <code>base</code> は最初の間隔、つまり最初の再試行までの待ち時間です。この値には3000msを使用することをお勧めします。
* <code>n</code> は、現在の呼び出しの前にリクエストが通らなかった数です。複数のスレッドやプロセスを使用して並行してAPIを呼び出している場合、<code>n</code>の値は現在のスレッド/プロセスにスコープされます。この値は、現在のスレッド/プロセスが、最後に成功した応答から何回 429 "Too Many Requests" エラーに遭遇したかを表します。
* <code>jitter</code> は 0 から <code>base</code> の間の乱数です。これは、複数のスレッド/プロセスが全く同時にAPIを呼び出さないように、リクエストを少しずつ分散させるために使用されます。システムが待機するたびに、この乱数値を再計算し <code>wait_interval</code> の合計に加算するか減算するか、ランダムで選択してください。


==== バックエンドとフロントエンドの分離 ====
基本的にteleportのサーバーを一度経由して、各種の踏み台サーバーにアクセスする。経由先が1個増えるが、そのおかげで監査ログを取得できたり、権限などを一括管理できる。
https://chatgpt.com/c/6747e923-6174-800b-8816-dd741721de45


SPA (Single Page Application) やJAMStackの影響で、バックエンドはデータを返すだけで、画面描画はフロントエンドが全部するというのが最近の流行。
ただ、teleportで監査ログを残すには、基本的にtshを経由する必要があり、既存のIDEなどのssh想定のソフトだと工夫が必要。tsh経由でやったり、rsyncで間にtshを挟むような工夫が必要。


SSR (Server Side Rendering) とCSR (Client Side Rendering) の違い。フロントエンドの高度化や分業などが理由とのこと。
===== Install =====
[https://goteleport.com/blog/how-to-configure-ssh-certificate-based-authentication/ How to configure SSH Certificate-Based Authentication]


SSRの利点。
[[https://goteleport.com/download/ Download Teleport: Secure and Easy Infrastructure Access | Teleport]] から自分のパソコンのtshをインストールする。


* SEO
以下の環境変数を設定する。
* 初期表示。
*TELEPORT_AUTH:
* 匿名。
* TELEPORT_LOGIN:
* TELEPORT_PROXY: teleportプロキシーサーバーのアドレス。重要。


SSRの課題。
===== tsh =====
teleportのコマンドラインクライアント。


* サーバー負荷: データとHTML作成を同時に行うから。
tsh loginでteleportにログインする。
* 分散困難:


キャッシュの活用がポイントになるとのこと。
環境変数


=== Network ===
[https://goteleport.com/docs/reference/cli/tsh/ tsh CLI reference | Teleport Docs]


==== ssh ====
* TELEPORT_AUTH:
* TELEPORT_LOGIN:
* TELEPORT_PROXY: teleportプロキシーサーバーのアドレス。重要。
上記3個が特に重要。


===== ssh-addの自動登録 =====
===== ProxyJump+ProxyCommand =====
ssh agentに秘密鍵の登録は以下のコマンド。
How To Use SSH ProxyJump and SSH ProxyCommand
ssh-add <秘密鍵のpath>
ただし、上記コマンドは再起動すると登録が消えるので毎回必要。


~/.ssh/configに以下の内容を記入しておくと、次回からkeychainから自動で読み込まれるらしい ([https://qiita.com/sonots/items/a6dec06f95fca4757d4a macOS で再起動しても ssh agent に秘密鍵を保持させ続ける二つの方法 #SSH - Qiita])。
https://goteleport.com/blog/ssh-proxyjump-ssh-proxycommand/
Host *
  UseKeychain yes
  AddKeysToAgent yes
うまくいかなかった。


[https://aifan.jp/2022/01/25/ssh-add%E3%82%92pc%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B%E5%BA%A6%E3%81%AB%E8%87%AA%E5%8B%95%E7%9A%84%E3%81%AB%E5%AE%9F%E8%A1%8C%E3%81%95%E3%81%9B%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E8%A8%AD%E5%AE%9A/ ssh-addをPC起動する度に自動的に実行させるための設定 | AIFAN]
~/.ssh/config のProxyJumpとProxyCommandの違いを整理する。


id_rsaの場合はIdentityFileを省略できるが、それ以外は指定が必要な模様。
どちらも中間サーバーを経由したリモートサーバーアクセスの指令。
Host *
  UseKeychain yes
  AddKeysToAgent yes
  IdentityFile ~/.ssh/id_ed25519


===== ssh経由でのリダイレクト出力 =====
* ProxyJump: 最も簡単な方法。OpenSSH v7,5以上で使用可能。中間サーバーでポート転送対応が前提条件。ProxyJumpは内部でProxyCommandを使う。
[https://superuser.com/questions/400714/how-to-remotely-write-to-a-file-using-ssh bash - How to remotely write to a file using SSH - Super User]
* ProxyCommand: ProxyJump搭乗前の方法。中間サーバーを介して標準入力と標準出力を転送して機能。


ssh経由で標準入力内容からファイルをリダイレクトで作成したいことがある。
ProxyJumpの方が現代的だが、ProxyCommandの方が柔軟性が高い。


sshのコマンド部分を文字列にすればOK。
ProxyJumpの使用例。
ssh user@remotehost -T "cat > /remotefile.txt" <<-EOT
{| class="wikitable"
Some text
|<code>ssh -J <jump server> <remote server>ssh -J <jump server1>,<jump server2>,<jump server3> <remote server></code>
EOT
|}
-Tで擬似端末を無効にしている。
ProxyCommand
{| class="wikitable"
===== パスフレーズの省略 =====
|<code>ssh -o ProxyCommand="ssh -W %h:%p <jump server>"</code> <code><remote server></code>
* [https://zenn.dev/luvmini511/articles/65786667221313 SSH パスフレーズ 省略したい!~ config 設定するか Keychain 登録自動化するか ~]
|}
* [https://madoverload.com/2022/04/29/mac-ssh-agent/ Macのssh-agent]
~/.ssh/configの例。
SSH多段接続時とgit cloneでSSH鍵参照時に、パスフレーズを要求される。毎回要求されるのが手間。これを省略する方法がある。
{| class="wikitable"
~/.ssh/configに以下の設定を記述する。
|<code>Host remoteserver</code>
Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519
* AddKeysToAgent=yesにすると、ssh-agentの実行時に自動的に鍵を追加する。
* UseKeychain=macOS専用。OSのキーチェーンからパスフレーズの検索を試みる。
* IdentityFile=SSH秘密鍵の絶対パス。デフォルトは~/.ssh/id_rsa。
上記3点で自動入力を試みる。
macOSで行う分には上記だけでパスワードは聞かれない。これをリモートでもやりたいなら、ssh-agentに登録が必要。
ログイン時に1回実行してくれたらいいので、ログインシェルの設定の~/.bash_profileに以下を記述。
echo 'ssh-add --apple-use-keychain' >>~/.bash_profile
これで端末の起動時に鍵を自動登録してくれるので、リモートでもパスフレーズを要求されない。


===== ssh_config =====
<code> HostName 192.168.200.200</code>
[https://linux.die.net/man/5/ssh_config ssh_config(5): OpenSSH SSH client config files - Linux man page]


重要な設定・構文がある。
<code> User dev</code>


====== TOKENS ======
<code> IdentityFile ~/.ssh/<your_key></code>
macのman ssh_configに詳しい。


使用可能な指令が限定されている。
<code> Port 2048</code>


HostName (Macのみ)


* %h=リモートホスト名。Hostの指定部。
<code> ## sample for</code> <code>ProxyJump</code>
* %p=リモートポート。


====== WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! ======
<code> ProxyJump user@<jumpserver></code>


* [https://www.niandc.co.jp/tech/20150729_2464/ ssh接続をする際に「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」と出てつながらない|テクニカルブログ|日本情報通信株式会社]
* [https://qiita.com/hnw/items/0eeee62ce403b8d6a23c 「SSHホスト鍵が変わってるよ!」と怒られたときの対処 #SSH - Qiita]


ssh example.comなどを実行すると、IPアドレスの振り直しなどで、ホストの公開鍵が変わっていた場合、中間者攻撃への対策として失敗する。
<code> ## sample for</code> <code>ProxyCommand</code>
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!    @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
SHA256:.
Please contact your system administrator.
Add correct host key in /Users/z.ken.senoo/.ssh/known_hosts to get rid of this message.
Offending RSA key in /Users/z.ken.senoo/.ssh/known_hosts:1
Host key for [example.com]:3023 has changed and you have requested strict checking.
Host key verification failed.
Connection closed by UNKNOWN port 65535
Connection closed by UNKNOWN port 65535


$HOME/.ssh/known_hostsの該当行を削除すれば解決する。以下のコマンドでも対応してくれる。
<code> ProxyCommand ssh -W %h:%p <jumpserver></code>
ssh-keygen -R example.com
|}
ssh remoteserver で<jumpserver> 経由でremoteserverに接続できる。


==== curl ====
一般的に、ProxyJumpが推奨される感がある。ただ、teleportを導入している場合、ProxyJump/ProxyCommandを使うと、tshを経由していないのでteleportにログが残らないらしい。
HTTPの通信のコマンドラインでの確認でよく使う。


===== Basic =====
===== tsh経由ssh =====
[https://curl.se/docs/tutorial.html curl - Tutorial]
ProxyJump/ProxyCommandを使わない場合、以下の形式でtshを使ってアクセスするのが基本。
* -X: メソッド指定
tsh ssh 踏み台サーバーホスト名
* -d/--data-urlencode: リクエストボディー (key=value)を指定。-X POSTも自動指定になる。
tsh sshでteleportサーバーが管理している踏み台サーバーが見えるので、そこに接続できる。tshの後のsshは基本的に通常のsshと同じなので、sshの後にsshのコマンドを連鎖でき、対象サーバーにも一発でアクセスできる。
curl -H "Content-Type: application/json" -d '{"name":"佐藤", "mail":"sato@example.com"}' localhost:5000/api/v1/users
tsh ssh -At <jump host> ssh -A <target host>
JSONで送信する場合、ヘッダー指定が必須。
-tでttyに繋いで標準入出力を接続。-Aはフォワーディング。ローカルのssh-addの情報などを連携できる。


<nowiki>*</nowiki>-F: multipart/formのform指定。
<jump host>の~/.ssh/configを用意しておくことで、<target host>にホスト名を指定したりできる。
curl -F "coolfiles=@fil1.gif;type=image/gif,fil2.txt,fil3.html"
  <nowiki>http://www.example.com/postit.cgi</nowiki>
@でfilename相当の指定。;でmime typeも指定できる。


@/</;type=自体を送信したい場合、-Fではなく、--form-stringを指定する。
ProxyJump/ProxyCommandと異なり、これだとちゃんとログを残せる。


===== curl: (60) SSL certificate problem: self-signed certificate =====
===== tsh経由scp =====
Ref: [https://linuxfan.info/curl-insecure curlで「自己署名証明書」を受け入れるには【curl: (60) SSL certificate problem: self signed certificate】 | LFI].


--insecureオプションを指定すると、localhostなどでの自己署名証明書を許可する。
* [https://goteleport.com/blog/teleport-files/ Teleport Files with SCP]
* [https://goteleport.com/docs/connect-your-client/tsh/ Using the tsh Command Line Tool | Teleport Docs]


===== curl: Failed writing body =====
tsh経由の踏み台サーバーへのファイル転送はやや工夫が必要。
[https://askubuntu.com/questions/1449492/right-after-piping-to-head-tail-curl-23-failure-writing-output-to-desti pipe - Right After piping to "head"/"tail": "curl: (23) Failure writing output to destination" - Ask Ubuntu]


以下のようにhead -n 1を指定するとcurlがエラーを出力する。
tsh scpというコマンドが一応ある。が、これはネストなどには未対応。やる場合、以下のように2回実行になる。
  curl -H "Content-Type: application/json; charset=utf-8" -H "X-HD-apitoken:$TOKEN"        -d "{\"dbSchemaId\":$dbSchemaId, \"limit\":1, \"offset\":$offset}"         <nowiki>https://$DOMAIN/$ACCOUNT/api/csvexport/version/1.0</nowiki> | head -n 1
  FR=test.file TO=/path/to/test.file
tsh scp $FR <jump host>:$TO; tsh ssh -At <jump host> scp $TO <target host>:$TO
高ではなく、rsyncを使えば一発でいける。
rsync -e "tsh ssh -A <jump host> ssh" ./test.file <target host>:~/
これが基本。


curl: Failed writing body
====== PhpStorm ======
curlは標準出力に全部書き込めたかチェックしているようで、head -n 1で切り捨てたらcurlはエラーになる。
[https://goteleport.com/docs/enroll-resources/server-access/guides/jetbrains-sftp/ JetBrains SFTP | Teleport Docs]


対策は、curl -sで出力を抑制するとのこと。これで解決。
teleportの公式にマニュアルがあるが、記述が非常に不親切。これだと踏み台サーバーにしかアクセスできない。その先にアクセスできない。


==== Teleport ====
多段SSHの設定を残しておいて、ファイル転送だけrsyncで行う形になる。


* [https://goteleport.com/docs/connect-your-client/teleport-connect/ Using Teleport Connect | Teleport Docs]
PhpStormのSSH configurationsのホスト名がスクリプトの引数に渡されるので、踏み台からAWSにsshでログインするホスト名やパソコンの~/.ssh/configのHostとの一致必要な点に注意する。
* [https://speakerdeck.com/gree_tech/greetechcon2023-session-a6 SSH から Teleport へ - Speaker Deck]
USERNAME=
 
IPV4=
踏み台サーバー (Jump server/Jump host) をよりよく管理するためのサーバーソフトウェア。
VPCID=
 
cat <<-EOT >>~/.ssh/config
アクセスログなどを一元管理できる。商用版とオープンソース版がある。
Host $VPCID
 
  ForwardAgent yes
基本的にteleportのサーバーを一度経由して、各種の踏み台サーバーにアクセスする。経由先が1個増えるが、そのおかげで監査ログを取得できたり、権限などを一括管理できる。
  User $USERNAME
 
  ServerAliveInterval 30
ただ、teleportで監査ログを残すには、基本的にtshを経由する必要があり、既存のIDEなどのssh想定のソフトだと工夫が必要。tsh経由でやったり、rsyncで間にtshを挟むような工夫が必要。
  SendEnv -LC_* -LANG
 
  ProxyJump $USERNAME@teleport.security:3023
===== tsh =====
   
teleportのコマンドラインクライアント。
Host $USERNAME
 
    ForwardAgent yes
tsh loginでteleportにログインする。
    ProxyJump $VPCID:22
 
    User $USERNAME
環境変数
    Hostname $USERNAME.example.com
    ServerAliveInterval 30
    SendEnv -LC_* -LANG
   
Host $USERNAME.$VPCID
    # for automatic upload by PHPStorm
    LocalForward 22224 $USERNAME.$VPCID:22
    # for XDebug
    RemoteForward 9000 localhost:9000
    ForwardAgent yes
   
Host db-*
  HostName $IPV4
  LocalForward 3307 localhost:22
  ProxyCommand ssh $VPCID -W %h:%p
  ForwardAgent yes
   
Host *
    AddKeysToAgent yes
    PasswordAuthentication no
    User $USERNAME
    ForwardAgent yes
    ServerAliveInterval 30
    IdentityFile ~/.ssh/id_ed25519
    # for macOS
    UseKeychain yes
EOT
こんな感じの多段SSHの設定を用意。
踏み台サーバーにも同じホスト名でアクセスできるように、以下のような内容の~/.ssh/configをまだならば設定しておく。
{| class="wikitable"
|<code>AWS_HOSTNAME=</code>


[https://goteleport.com/docs/reference/cli/tsh/ tsh CLI reference | Teleport Docs]
<code>IPV4=</code>


* TELEPORT_PROXY: teleportプロキシーサーバーのアドレス。重要。
<code>VPCID=</code>


===== ProxyJump+ProxyCommand =====
<code>tsh ssh -A $VPCID "cat >>~/.ssh/config"</code> <code><<-EOT</code>
How To Use SSH ProxyJump and SSH ProxyCommand


https://goteleport.com/blog/ssh-proxyjump-ssh-proxycommand/
<code>Host $AWS_HOSTNAME</code>


~/.ssh/config のProxyJumpとProxyCommandの違いを整理する。
<code> HostName $IPV4</code>


どちらも中間サーバーを経由したリモートサーバーアクセスの指令。
<code>EOT</code>
|}


* ProxyJump: 最も簡単な方法。OpenSSH v7,5以上で使用可能。中間サーバーでポート転送対応が前提条件。ProxyJumpは内部でProxyCommandを使う。
* ProxyCommand: ProxyJump搭乗前の方法。中間サーバーを介して標準入力と標準出力を転送して機能。


ProxyJumpの方が現代的だが、ProxyCommandの方が柔軟性が高い。
rsync executable


ProxyJumpの使用例。
rsyncで使用する (-eオプション)、以下の内容のシェルスクリプトを作成して実行権限を付与して任意の場所 (例: ~/project/tsh_ssh.sh) に配置する。
{| class="wikitable"
{| class="wikitable"
|<code>ssh -J <jump server> <remote server>ssh -J <jump server1>,<jump server2>,<jump server3> <remote server></code>
|<code>cd ~/project/</code>
|}
ProxyCommand
{| class="wikitable"
|<code>ssh -o ProxyCommand="ssh -W %h:%p <jump server>"</code> <code><remote server></code>
|}
~/.ssh/configの例。
{| class="wikitable"
|<code>Host remoteserver</code>


<code> HostName 192.168.200.200</code>
<code>cat <<-'EOT'</code> <code>>tsh_ssh.sh</code>


<code> User dev</code>
<code>tsh ssh -A <jump host> ssh $@</code>


<code> IdentityFile ~/.ssh/<your_key></code>
<code>EOT</code>


<code> Port 2048</code>  
<code>chmod +x tsh_ssh.sh</code>
|}




<code> ## sample for</code> <code>ProxyJump</code>


<code> ProxyJump user@<jumpserver></code>
PhpStorm設定


PhpStormで以下を設定する。


<code> ## sample for</code> <code>ProxyCommand</code>
* [Tools]-[Deployment]-[Configuration]
* [+]-[SFTP]
* [Create New Server]-[New server name: 任意の名前 (例=rsync)]-[OK]
* [Connection] タブを以下に設定。
*# Type=SFTP
*# SSH configuration=以下を設定。
*## Host: <ホスト名> (例: ~/.ssh/configと踏み台サーバーの~/.ssh/configのホスト名と同じにする)
*## User name: ユーザー名
*## Port: 22
*## Authentication type: OpenSSH config and authentication agent
*# Root path=転送先のベース。
*# [☑️Use Rsync for download/upload/sync]
*# Rsync Settings=以下を設定。
*## Shell executable path=tsh_ssh.shのパス (例=~/project/tsh_ssh.sh)
* [Mappings] タブを以下に設定。
*# Local path: ローカルパソコンのディレクトリー
*# Deployment path: /
*# Web path: /
* [Settings]-[Build, Execution, Development]-[Development]-[Options]-[Upload changed files automatically to the default server]=[On explicit save action]
*# ☑️Delete remote files when local are deleted


<code> ProxyCommand ssh -W %h:%p <jumpserver></code>
以上で完了。後は同期したいファイルをPhpStormで開いて、右クリック-[Deployment]-[Upload to]/[Download from] でファイル転送できる。
|}
ssh remoteserver で<jumpserver> 経由でremoteserverに接続できる。


一般的に、ProxyJumpが推奨される感がある。ただ、teleportを導入している場合、ProxyJump/ProxyCommandを使うと、tshを経由していないのでteleportにログが残らないらしい。
[☑️Use Rsync for download/upload/sync] のチェックを外せば、rsyncを使わないファイル転送になる。


===== tsh経由ssh =====
=== Wireshark ===
ProxyJump/ProxyCommandを使わない場合、以下の形式でtshを使ってアクセスするのが基本。
tsh ssh 踏み台サーバーホスト名
tsh sshでteleportサーバーが管理している踏み台サーバーが見えるので、そこに接続できる。tshの後のsshは基本的に通常のsshと同じなので、sshの後にsshのコマンドを連鎖でき、対象サーバーにも一発でアクセスできる。
tsh ssh -At <jump host> ssh -A <target host>
-tでttyに繋いで標準入出力を接続。-Aはフォワーディング。ローカルのssh-addの情報などを連携できる。


<jump host>の~/.ssh/configを用意しておくことで、<target host>にホスト名を指定したりできる。
==== TLS ====
Ref: [https://www.toyo.co.jp/onetech_blog/articles/detail/id=36994 SSL/TLSの復号#1 ~Wiresharkの設定~ | 東陽テクニカ | “はかる”技術で未来を創る | ワン・テクノロジーズ・カンパニー].


ProxyJump/ProxyCommandと異なり、これだとちゃんとログを残せる。
Wiresharkで通信パケットを確認する場合、デフォルトでTLSで暗号化されているので、内容がわからない。WiresharkでTLSに対応しておく必要がある。


===== tsh経由scp =====
[Preferences]-[Protocols]-[TCP] を選ぶ。


* [https://goteleport.com/blog/teleport-files/ Teleport Files with SCP]
* ☑Allow subdissector to reassemble TCP stream
* [https://goteleport.com/docs/connect-your-client/tsh/ Using the tsh Command Line Tool | Teleport Docs]
* ☑Reassemble out-of-order semgemnts
 
上記をチェックしておく。デフォルトでチェックされていた。
 
続いて、セッションごとのPre-Master Secretを登録する。
 
Chrome/Firefoxだと、環境変数SSLKEYLOGFILEを設定すれば、このファイルにTLSセッションキーを出力するので、これをWiresharkで読み込むことで、復号対応する。


tsh経由の踏み台サーバーへのファイル転送はやや工夫が必要。
以下のコマンド相当で、任意のファイル・場所にログファイルを指定する。
export SSLKEYLOGFILE=/tmp/sslkey.log
Macだとlaunchctlで設定しておくといい。これでWebブラウザー経由の場合は見えるようになる。


tsh scpというコマンドが一応ある。が、これはネストなどには未対応。やる場合、以下のように2回実行になる。
=== Security ===
FR=test.file TO=/path/to/test.file
tsh scp $FR <jump host>:$TO; tsh ssh -At <jump host> scp $TO <target host>:$TO
高ではなく、rsyncを使えば一発でいける。
rsync -e "tsh ssh -A <jump host> ssh" ./test.file <target host>:~/
これが基本。


====== PhpStorm ======
==== DoS攻撃 ====
[https://goteleport.com/docs/enroll-resources/server-access/guides/jetbrains-sftp/ JetBrains SFTP | Teleport Docs]
いくつか対策方法がある。


teleportの公式にマニュアルがあるが、記述が非常に不親切。これだと踏み台サーバーにしかアクセスできない。その先にアクセスできない。
* [https://lite.ip2location.com/ip-address-ranges-by-country?lang=ja 国別のIPアドレス範囲]
* [https://rakko.tools/tools/11/ IPアドレスから住所検索:国、地域の特定 | ラッコツールズ🔧]


多段SSHの設定を残しておいて、ファイル転送だけrsyncで行う形になる。
サーバーログにIPアドレスが残るから、それで攻撃元の国を特定して、該当国を一括アクセス拒否。これが効果あるかもしれない。


PhpStormのSSH configurationsのホスト名がスクリプトの引数に渡されるので、踏み台からAWSにsshでログインするホスト名やパソコンの~/.ssh/configのHostとの一致必要な点に注意する。
攻撃元の国は途上国とかが多いだろうから。IPアドレスは簡単に変更できるが、国を変えるのはたいへんだろう。
USERNAME=
 
IPV4=
==== バリデーションの実装 ====
VPCID=
 
cat <<-EOT >>~/.ssh/config
* [https://teratail.com/questions/81861 フロント側で入力チェックをしていればサーバー側では入力チェックは必要ない?]
Host $VPCID
* [https://qiita.com/mi2__user/items/f2f415ccbb0a625c8647 フロントエンドの"バリデーション"は最低限の方がいいらしい。 #TypeScript - Qiita]
  ForwardAgent yes
 
  User $USERNAME
基本的に、バックエンドで主にチェックして、フロントエンドはUXの向上目的で実装する。データの重複チェックはDBアクセスが必要だったりするから。また、API経由などフロントがそもそもないケースもある。
  ServerAliveInterval 30
 
  SendEnv -LC_* -LANG
ただ、社内システムのような、画面経由でしか使わない。悪者がほぼいないと思われるケースは、フロントエンドでの検証だけでも十分に感じる。
  ProxyJump $USERNAME@teleport.security:3023
 
   
==== 二重送信 ====
Host $USERNAME
 
    ForwardAgent yes
* [https://www.youfit.co.jp/archives/4545 フォームの二重送信を防止する方法 - 福岡・東京のシステム開発会社 (株)ユーフィット]
    ProxyJump $VPCID:22
* [https://qiita.com/syobochim/items/120109315f671918f28d さいきょうの二重サブミット対策 #JavaScript - Qiita]
    User $USERNAME
 
    Hostname $USERNAME.example.com
submitボタンのダブルクリック、リロード、ブラウザーバック・フォワードなど、フォーム周りで注意が必要な保安要素がある。
    ServerAliveInterval 30
 
    SendEnv -LC_* -LANG
# ボタン連打
   
# ブラウザーバック
Host $USERNAME.$VPCID
# リロード (PRG)
    # for automatic upload by PHPStorm
    LocalForward 22224 $USERNAME.$VPCID:22
    # for XDebug
    RemoteForward 9000 localhost:9000
    ForwardAgent yes
   
Host db-*
  HostName $IPV4
  LocalForward 3307 localhost:22
  ProxyCommand ssh $VPCID -W %h:%p
  ForwardAgent yes
   
Host *
    AddKeysToAgent yes
    PasswordAuthentication no
    User $USERNAME
    ForwardAgent yes
    ServerAliveInterval 30
    IdentityFile ~/.ssh/id_ed25519
    # for macOS
    UseKeychain yes
EOT
こんな感じの多段SSHの設定を用意。
踏み台サーバーにも同じホスト名でアクセスできるように、以下のような内容の~/.ssh/configをまだならば設定しておく。
{| class="wikitable"
|<code>AWS_HOSTNAME=</code>


<code>IPV4=</code>
項目ごとにすべき対策が異なる。


<code>VPCID=</code>
===== 連打 =====


<code>tsh ssh -A $VPCID "cat >>~/.ssh/config"</code> <code><<-EOT</code>
* [https://www.youfit.co.jp/archives/4545 フォームの二重送信を防止する方法 - 福岡・東京のシステム開発会社 (株)ユーフィット]
* [https://qiita.com/syobochim/items/120109315f671918f28d さいきょうの二重サブミット対策 #JavaScript - Qiita]
* [https://codezine.jp/article/detail/769 JavaScriptを利用してフォームの二重送信を防止する|CodeZine(コードジン)]
* [https://blog.nisesagi.com/3150/ JavaScriptでformの2重送信を防止する | にせサギ ネットサギ体験ブログ]
* [https://yutaihara.com/archives/569 Javascriptで送信ボタン二度押しによる二重送信を防止する方法 | Yuta Ihara.com]


<code>Host $AWS_HOSTNAME</code>
基本は、ボタンのsubmitのイベント内でdisabled=trueでの無効化。


<code> HostName $IPV4</code>
似た考え方で、スプラッシュのモーダル表示もあり。これがわかりやすいかもしれない。
 
$("form").submit(function() {
<code>EOT</code>
  var self = this;
|}
  $(":submit", self).prop("disabled", true);
  setTimeout(function() {
    $(":submit", self).prop("disabled", false);
  }, 10000);
});
停止にしたら、二度通せなくなるので、タイムアウトで戻すとよい。
 
=== Browser ===


==== Chromium ====


rsync executable
===== Extension =====
Chromme系で愛用拡張機能を列挙する。


rsyncで使用する (-eオプション)、以下の内容のシェルスクリプトを作成して実行権限を付与して任意の場所 (例: ~/project/tsh_ssh.sh) に配置する。
* [https://chromewebstore.google.com/detail/create-link/gcmghdmnkfdbncmnmlkkglmnnhagajbm Create Link]:
{| class="wikitable"
|<code>cd ~/project/</code>


<code>cat <<-'EOT'</code> <code>>tsh_ssh.sh</code>
===== Profile =====
https://chatgpt.com/c/67aca944-1fcc-800b-973e-7bf3207b9b91


<code>tsh ssh -A <jump host> ssh $@</code>
Webサイトのアカウントを切り替えたい場合、Webブラウザーのプロファイル機能で、アカウント情報を分離できる (Googleアカウントではなくて)。


<code>EOT</code>
これでA用、B用など用途ごとにプロファイルを作って、それでセッションやブックマークなどを分けられる。


<code>chmod +x tsh_ssh.sh</code>
==== devtool/開発者ツール ====
|}


===== イベントリスナー =====
[https://yuzu441.hateblo.jp/entry/2016/12/12/120000 要素に設定されているイベントを調べよう - ゆずめも]


[Elements]-[Event Listeners]-[handler]-右クリック-[Show function definition] でイベントリスナー関数の定義を確認できる。


PhpStorm設定
===== イベント監視 =====
[https://stackoverflow.com/questions/3787555/how-to-find-out-which-javascript-events-fired How to find out which JavaScript events fired? - Stack Overflow]


PhpStormで以下を設定する。
monitorEvent関数で監視できるらしい。他に、FirefoxのFirebugのlog eventsでも監視できるらしい。


* [Tools]-[Deployment]-[Configuration]
===== Network conditions =====
* [+]-[SFTP]
開発者ツールの[Network]タブを開いてリロードしても、[No internet]と表示されることがある。
* [Create New Server]-[New server name: 任意の名前 (例=rsync)]-[OK]
* [Connection] タブを以下に設定。
*# Type=SFTP
*# SSH configuration=以下を設定。
*## Host: <ホスト名> (例: ~/.ssh/configと踏み台サーバーの~/.ssh/configのホスト名と同じにする)
*## User name: ユーザー名
*## Port: 22
*## Authentication type: OpenSSH config and authentication agent
*# Root path=転送先のベース。
*# [☑️Use Rsync for download/upload/sync]
*# Rsync Settings=以下を設定。
*## Shell executable path=tsh_ssh.shのパス (例=~/project/tsh_ssh.sh)
* [Mappings] タブを以下に設定。
*# Local path: ローカルパソコンのディレクトリー
*# Deployment path: /
*# Web path: /
* [Settings]-[Build, Execution, Development]-[Development]-[Options]-[Upload changed files automatically to the default server]=[On explicit save action]
*# ☑️Delete remote files when local are deleted


以上で完了。後は同期したいファイルをPhpStormで開いて、右クリック-[Deployment]-[Upload to]/[Download from] でファイル転送できる。
これはオプション設定の問題。上のツールバーの[Disable cache]の右が[Offline] だとこうなる。これを[No throttling]にすると解決する。クリックミスだと思われる。


[☑️Use Rsync for download/upload/sync] のチェックを外せば、rsyncを使わないファイル転送になる。
==== Safari ====


=== Wireshark ===
===== Windows Safari =====


==== TLS ====
* [https://web.archive.org/web/20220220134447/https://jp.techcrunch.com/2012/07/27/20120725apple-safari-for-windows-ends/ Appleは静かにWindows版Safariの開発から手を引いてしまったのだろうか? | TechCrunch Japan]
Ref: [https://www.toyo.co.jp/onetech_blog/articles/detail/id=36994 SSL/TLSの復号#1 ~Wiresharkの設定~ | 東陽テクニカ | “はかる”技術で未来を創る | ワン・テクノロジーズ・カンパニー].
* [http://web.archive.org/web/20120728130701/https://support.apple.com/kb/DL1531 Safari 5.1.7 for Windows]


Wiresharkで通信パケットを確認する場合、デフォルトでTLSで暗号化されているので、内容がわからない。WiresharkでTLSに対応しておく必要がある。
一応ある。2012-05-09のSafari 5.1.7までWindows版が提供されていた。DL1531。


[Preferences]-[Protocols]-[TCP] を選ぶ。
===== 開発者ツール =====
[https://www.e-bird.biz/blog/dev-ios/ PCでスマホサイトを見る方法 – Safari編|東京渋谷のWeb制作会社・ホームページ制作会社|株式会社イー・バード]


* ☑Allow subdissector to reassemble TCP stream
Safariの開発者ツールは癖がある。
* ☑Reassemble out-of-order semgemnts


上記をチェックしておく。デフォルトでチェックされていた。
[設定]-[詳細]-[☑️Webデベロッパ用の機能を表示]


続いて、セッションごとのPre-Master Secretを登録する。
[開発]-[レスポンシブデザインモードにする]


Chrome/Firefoxだと、環境変数SSLKEYLOGFILEを設定すれば、このファイルにTLSセッションキーを出力するので、これをWiresharkで読み込むことで、復号対応する。
===== スーパーリロード =====
[https://www.support.allmovie.jp/blog/20210527115217/ サポートへようこそ|メールのトラブルやホームページに関するお問い合わせ、 CMS操作方法など各種サポート情報をご案内しております。/各ブラウザでの強制リフレッシュ(スーパーリロード)]


以下のコマンド相当で、任意のファイル・場所にログファイルを指定する。
Shift-更新ボタン
export SSLKEYLOGFILE=/tmp/sslkey.log
Macだとlaunchctlで設定しておくといい。これでWebブラウザー経由の場合は見えるようになる。


=== Security ===
=== Other ===


==== DoS攻撃 ====
==== Tool ====
いくつか対策方法がある。


* [https://lite.ip2location.com/ip-address-ranges-by-country?lang=ja 国別のIPアドレス範囲]
* [https://web-toolbox.dev/ Web ToolBox | 開発者向けのオンラインツール]
* [https://rakko.tools/tools/11/ IPアドレスから住所検索:国、地域の特定 | ラッコツールズ🔧]
* [https://tm-webtools.com/ TM - WebTools]


サーバーログにIPアドレスが残るから、それで攻撃元の国を特定して、該当国を一括アクセス拒否。これが効果あるかもしれない。
いくつかWeb関係の開発で役立つツール集を公開しているサイトがある。


攻撃元の国は途上国とかが多いだろうから。IPアドレスは簡単に変更できるが、国を変えるのはたいへんだろう。
==== localhost ====


==== バリデーションの実装 ====
* [[wikipedia:Special-use_domain_name|Special-use domain name - Wikipedia]]
* [https://ja.wikipedia.org/wiki/.localhost .localhost - Wikipedia]


* [https://teratail.com/questions/81861 フロント側で入力チェックをしていればサーバー側では入力チェックは必要ない?]
RFC 6761 で規定。RFC 2606<nowiki/>で予約。DNSに登録されることはないため、テスト目的で使用可能。ループバック (送信元にそのまま返す) インターフェイス。
* [https://qiita.com/mi2__user/items/f2f415ccbb0a625c8647 フロントエンドの"バリデーション"は最低限の方がいいらしい。 #TypeScript - Qiita]


基本的に、バックエンドで主にチェックして、フロントエンドはUXの向上目的で実装する。データの重複チェックはDBアクセスが必要だったりするから。また、API経由などフロントがそもそもないケースもある。
IPv4=127.0.0.1/IPv6=::1とされている。


ただ、社内システムのような、画面経由でしか使わない。悪者がほぼいないと思われるケースは、フロントエンドでの検証だけでも十分に感じる。
==== DB vs. file ====
https://chatgpt.com/share/67f78855-b640-800b-84c9-ed3ada7fef48


==== 二重送信 ====
データはアクセス元によって、速度や負荷が異なるらしい。それぞれ特徴がある。


* [https://www.youfit.co.jp/archives/4545 フォームの二重送信を防止する方法 - 福岡・東京のシステム開発会社 (株)ユーフィット]
* ファイル (JSON/php):
* [https://qiita.com/syobochim/items/120109315f671918f28d さいきょうの二重サブミット対策 #JavaScript - Qiita]
* インメモリーDB: Redis
* RDB: 排他処理。検索・集計。書込用。


submitボタンのダブルクリック、リロード、ブラウザーバック・フォワードなど、フォーム周りで注意が必要な保安要素がある。
書き込みの最終はRDBとして、そこからよく使うものを、書き込みの少ないものを、インメモリーDBやファイルに引き上げるような感じがする。


# ボタン連打
== Shared Host ==
# ブラウザーバック
# リロード (PRG)


項目ごとにすべき対策が異なる。
=== Free ===
無料で使用可能な共用ホスティングサービスがある。


===== 連打 =====
==== スタードメイン無料サーバー ====
ドメインをセットで利用する必要があるものの、スタードメインのスタードメイン無料サーバーがけっこういい。


* [https://www.youfit.co.jp/archives/4545 フォームの二重送信を防止する方法 - 福岡・東京のシステム開発会社 (株)ユーフィット]
[https://www.star-domain.jp/service/free_server.php 無料レンタルサーバー | スタードメイン - ドメイン取得 100円(税込)~]
* [https://qiita.com/syobochim/items/120109315f671918f28d さいきょうの二重サブミット対策 #JavaScript - Qiita]
* [https://codezine.jp/article/detail/769 JavaScriptを利用してフォームの二重送信を防止する|CodeZine(コードジン)]
* [https://blog.nisesagi.com/3150/ JavaScriptでformの2重送信を防止する | にせサギ ネットサギ体験ブログ]
* [https://yutaihara.com/archives/569 Javascriptで送信ボタン二度押しによる二重送信を防止する方法 | Yuta Ihara.com]


基本は、ボタンのsubmitのイベント内でdisabled=trueでの無効化。
jpドメインの金額が相場の中では安い方で、それに無料サーバーがついていくる点。


似た考え方で、スプラッシュのモーダル表示もあり。これがわかりやすいかもしれない。
* ディスク容量 20GB
$("form").submit(function() {
* DB 1GB
  var self = this;
  $(":submit", self).prop("disabled", true);
  setTimeout(function() {
    $(":submit", self).prop("disabled", false);
  }, 10000);
});
停止にしたら、二度通せなくなるので、タイムアウトで戻すとよい。


=== Browser ===
ただし、SSHやコマンドは使えないので、FTPでWordPressを展開して設置するとか、そういう簡単な使い方だけ。ただ、それでもWordPressでWebサイトを構築するくらいなら十分だと思う。


==== Chromium ====
=== CORESERVER ===


===== Extension =====
==== メール ====
Chromme系で愛用拡張機能を列挙する。


* [https://chromewebstore.google.com/detail/create-link/gcmghdmnkfdbncmnmlkkglmnnhagajbm Create Link]:
* [https://www2.bwt.jp/wiki/?Custom_Filter_of_Coreserver Custom_Filter_of_Coreserver - PukiWiki]
* [https://help.coreserver.jp/manual/v2/spam-filter/ スパムフィルターの設定 | マニュアル | サポート | レンタルサーバー CORESERVER(コアサーバー)]
* [https://help.coreserver.jp/manual/v1/customfilter/ カスタムフィルターの設定 | マニュアル | サポート | レンタルサーバー CORESERVER(コアサーバー)]


===== Profile =====
情報
https://chatgpt.com/c/67aca944-1fcc-800b-973e-7bf3207b9b91


Webサイトのアカウントを切り替えたい場合、Webブラウザーのプロファイル機能で、アカウント情報を分離できる (Googleアカウントではなくて)。
* [https://www2.bwt.jp/wiki/?CoreServer_Mail_Custom CoreServer_Mail_Custom - PukiWiki]
* [https://bwt.blog.ss-blog.jp/2021-03-28 coreserverのメール設定:BWT Lab.:SSブログ]
* [https://qwerty.work/blog/2017/01/valueserver-spammail-filter-rule.php バリューサーバーのフィルター設定でスパムメール(迷惑メール)対策する方法 - QWERTY.WORK]
* [https://awmt.jp/dekirukana/archives/2253 コアサーバー V1にてカスタムフィルターで「ごみ箱」を指定したときの確認方法 – AWMTの、できるかな?]


これでA用、B用など用途ごとにプロファイルを作って、それでセッションやブックマークなどを分けられる。
ルールが特殊なので注意する。


==== devtool/開発者ツール ====
ゴミ箱に振り分ける場合。


===== イベントリスナー =====
順1 で[<code>./.Trash</code>] を指定
[https://yuzu441.hateblo.jp/entry/2016/12/12/120000 要素に設定されているイベントを調べよう - ゆずめも]


[Elements]-[Event Listeners]-[handler]-右クリック-[Show function definition] でイベントリスナー関数の定義を確認できる。
順2


===== イベント監視 =====
* 条件:  [<code>.*</code>]
[https://stackoverflow.com/questions/3787555/how-to-find-out-which-javascript-events-fired How to find out which JavaScript events fired? - Stack Overflow]
* 処理:  <code>./</code>、に振り分ける


monitorEvent関数で監視できるらしい。他に、FirefoxのFirebugのlog eventsでも監視できるらしい。
条件部分には正規表現が使えるように見える。


===== Network conditions =====
破棄にしないといけない。転送する場合、カスタムフィルターの中に転送を入れる。条件を.*にする。
開発者ツールの[Network]タブを開いてリロードしても、[No internet]と表示されることがある。


これはオプション設定の問題。上のツールバーの[Disable cache]の右が[Offline] だとこうなる。これを[No throttling]にすると解決する。クリックミスだと思われる。
カスタムフィルターにくせがある。


==== Safari ====
* エスケープ(\を前置する)が必要な文字は「'」「"」「|」「`」「~」「?」「!」


===== Windows Safari =====
==== Value Domain ネットde診断 byGMO ====


* [https://web.archive.org/web/20220220134447/https://jp.techcrunch.com/2012/07/27/20120725apple-safari-for-windows-ends/ Appleは静かにWindows版Safariの開発から手を引いてしまったのだろうか? | TechCrunch Japan]
* [https://www.value-domain.com/information/detail/?no=20240606-1 弊社レンタルサーバー上で運用中のドメインにおける自動セキュリティ診断開始のお知らせ | お知らせ - バリュードメイン]
* [http://web.archive.org/web/20120728130701/https://support.apple.com/kb/DL1531 Safari 5.1.7 for Windows]
* [https://www.value-domain.com/security/net-de-shindan/ Value Domain ネットde診断 byGMO - バリュードメイン]


一応ある。2012-05-09のSafari 5.1.7までWindows版が提供されていた。DL1531。
2024-06-07 Friからバリュードメイン系の利用者に無料で提供しているセキュリティー診断ツール。


===== 開発者ツール =====
==== CGI ====
[https://www.e-bird.biz/blog/dev-ios/ PCでスマホサイトを見る方法 – Safari編|東京渋谷のWeb制作会社・ホームページ制作会社|株式会社イー・バード]


Safariの開発者ツールは癖がある。
* [https://senooken.jp/post/2020/02/21/3905/ CORESERVERでのFastCGI/CGI版PHPの利用手順 – senooken JP]
* [https://help.coreserver.jp/faq/php-fast-cgi/ FastCGI版PHP 各バージョンのPHP設定方法 | よくある質問 | サポート | レンタルサーバー CORESERVER(コアサーバー)]
* [https://help.coreserver.jp/faq/php-cgi/ PHPをCGIとして動かす方法を教えてください | よくある質問 | サポート | レンタルサーバー CORESERVER(コアサーバー)]
* [https://engineer-milione.com/create/python-execution.html レンタルサーバー各社でのPythonの実行方法まとめ]


[設定]-[詳細]-[☑️Webデベロッパ用の機能を表示]
CORESERVERでのCGIの設定方法がある。
 
{| class="wikitable"
[開発]-[レスポンシブデザインモードにする]
|+CORESERVERのFastCGI版PHPとCGI版PHPの設定方法
 
!項目
===== スーパーリロード =====
!FastCGI
[https://www.support.allmovie.jp/blog/20210527115217/ サポートへようこそ|メールのトラブルやホームページに関するお問い合わせ、 CMS操作方法など各種サポート情報をご案内しております。/各ブラウザでの強制リフレッシュ(スーパーリロード)]
!CGI
 
|-
Shift-更新ボタン
|バージョンの変更
 
|管理画面
=== Other ===
|<code>.htaccess</code>内の
 
<code>AddHandler application/x-httpd-phpcgiXX .php</code>
==== Tool ====
|-
 
|設定ディレクトリー
* [https://web-toolbox.dev/ Web ToolBox | 開発者向けのオンラインツール]
| colspan="2" rowspan="1" |<code>/virtual/<username>/public_html/.fast-cgi-bin/</code>
* [https://tm-webtools.com/ TM - WebTools]
|-
|CGIの実行ファイル
|<code>phpXX.fcgi</code>
|<code>phpXX.cgi</code>
|-
|PHPの設定ファイル
|<code>phpXX.ini</code>
|<code>php.ini</code>
|-
|設定の反映タイミング
|バージョン切替時
|即時
|}
~/public_html/.fast-cgi-bin/のphpXX.fcgi phpXX.cgiがCGIの実行ファイル。このファイルか最後の行のexecのパスを変更すると、自前コマンドに変更可能。


いくつかWeb関係の開発で役立つツール集を公開しているサイトがある。
FastCGIは管理画面からバージョンを変更したタイミングで反映される。ただ、ファイル拡張子が.phpじゃないとこのFastCGIが実行されない模様。


==== localhost ====
CGIは.htaccessに以下の内容を記述してCGI板PHPのバージョンを指定する。
AddHandler application/x-httpd-phpcgiXX .php
cgiのファイルには実行権限が必要。
chmod +x py.py
拡張子がないとダメな模様。加えて、.htaccessに以下の記述。
AddHandler cgi-script .py
これでpy.pyで動作はする。


* [[wikipedia:Special-use_domain_name|Special-use domain name - Wikipedia]]
拡張子じゃなくてファイル名で実行したい場合、SetHandlerでしていする ([https://senooken.jp/post/2019/06/01/2333/ AddType, AddHandler, SetHandlerの違い – senooken JP])。
* [https://ja.wikipedia.org/wiki/.localhost .localhost - Wikipedia]
<FilesMatch py$>
    SetHandler cgi-script
</FilesMatch>
これでpyでもアクセスできる。


RFC 6761 で規定。RFC 2606<nowiki/>で予約。DNSに登録されることはないため、テスト目的で使用可能。ループバック (送信元にそのまま返す) インターフェイス。
FastCGI版の場合、以下のような設定でファイル名でマッチさせれば実行できそうな気もするが。
 
<FilesMatch \.php$>
IPv4=127.0.0.1/IPv6=::1とされている。
    SetHandler application/x-httpd-php
</FilesMatch>
500
<FilesMatch gnusocial$>
        SetHandler application/x-httpd-php
</FilesMatch>
pythonがphpとして認識され、テキストがそのまま表示される。


== Shared Host ==
SetHandler fcgid-scriptにしたらFastCGIで動作する。プログラムがFastCGI対応になっている必要がある。
<FilesMatch gnusocial$>
        SetHandler fcgid-script
</FilesMatch>


=== Free ===
== Analytics ==
無料で使用可能な共用ホスティングサービスがある。


==== スタードメイン無料サーバー ====
==== Exam ====
ドメインをセットで利用する必要があるものの、スタードメインのスタードメイン無料サーバーがけっこういい。
<nowiki>##</nowiki> About


[https://www.star-domain.jp/service/free_server.php 無料レンタルサーバー | スタードメイン - ドメイン取得 100円(税込)~]
<nowiki>https://gnusocial.jp/notice/4506679</nowiki>


jpドメインの金額が相場の中では安い方で、それに無料サーバーがついていくる点。
<nowiki>###</nowiki> 全般


* ディスク容量 20GB
- マーケティング・ビジネス実務検定
* DB 1GB


ただし、SSHやコマンドは使えないので、FTPでWordPressを展開して設置するとか、そういう簡単な使い方だけ。ただ、それでもWordPressでWebサイトを構築するくらいなら十分だと思う。
- IMA検定


=== CORESERVER ===
- Web検定


==== メール ====
- ネットマーケティング検定


* [https://www2.bwt.jp/wiki/?Custom_Filter_of_Coreserver Custom_Filter_of_Coreserver - PukiWiki]
<nowiki>###</nowiki> 解析系
* [https://help.coreserver.jp/manual/v2/spam-filter/ スパムフィルターの設定 | マニュアル | サポート | レンタルサーバー CORESERVER(コアサーバー)]
* [https://help.coreserver.jp/manual/v1/customfilter/ カスタムフィルターの設定 | マニュアル | サポート | レンタルサーバー CORESERVER(コアサーバー)]


情報
- ウェブ解析士


* [https://www2.bwt.jp/wiki/?CoreServer_Mail_Custom CoreServer_Mail_Custom - PukiWiki]
- GAIQ
* [https://bwt.blog.ss-blog.jp/2021-03-28 coreserverのメール設定:BWT Lab.:SSブログ]
* [https://qwerty.work/blog/2017/01/valueserver-spammail-filter-rule.php バリューサーバーのフィルター設定でスパムメール(迷惑メール)対策する方法 - QWERTY.WORK]
* [https://awmt.jp/dekirukana/archives/2253 コアサーバー V1にてカスタムフィルターで「ごみ箱」を指定したときの確認方法 – AWMTの、できるかな?]


ルールが特殊なので注意する。
- 統計検定


ゴミ箱に振り分ける場合。
- Webアナリスト検定


順1 で[<code>./.Trash</code>] を指定
GAIQが無料だしどうせ使うからいいかな。


順2
<nowiki>https://wacul-ai.com/blog/access-analysis/google-analytics-method/gaiq/</nowiki>


* 条件:  [<code>.*</code>]
<nowiki>https://www.plan-b.co.jp/blog/seo/12792/</nowiki>
* 処理:  <code>./</code>、に振り分ける


条件部分には正規表現が使えるように見える。
<nowiki>##</nowiki> URL


破棄にしないといけない。転送する場合、カスタムフィルターの中に転送を入れる。条件を.*にする。
- <nowiki>https://ceres-inc.jp/business-tips/recommended-webmarketing-shikaku/</nowiki>


カスタムフィルターにくせがある。
- <nowiki>https://mynavi-creator.jp/blog/article/qualification-for-web-marketer</nowiki>


* エスケープ(\を前置する)が必要な文字は「'」「"」「|」「`」「~」「?」「!」
- <nowiki>https://www.icloud.co.jp/article/exam/features-and-5-acquisition-benefits.html</nowiki>


==== Value Domain ネットde診断 byGMO ====
- <nowiki>https://digitor.jp/textbook/web-analytical-qualification/</nowiki>


* [https://www.value-domain.com/information/detail/?no=20240606-1 弊社レンタルサーバー上で運用中のドメインにおける自動セキュリティ診断開始のお知らせ | お知らせ - バリュードメイン]
=== Tool ===
* [https://www.value-domain.com/security/net-de-shindan/ Value Domain ネットde診断 byGMO - バリュードメイン]
サイト分析用のツールがいくつかある ([https://hidesunblog.com/blog-ranking-sites/ 2023年ブログランキング!おすすめブログランキングサイト比較【一般人向け】])。


2024-06-07 Friからバリュードメイン系の利用者に無料で提供しているセキュリティー診断ツール。
* SimilarWeb
* Ubersuggest
* ahrefs
* Googleキーワードプランナー


==== CGI ====
=== 閲覧数取得 ===
出典: [https://affiliate-jpn.com/archives/5595 GoogleAnalyticsで自サイトの人気記事ランキングを表示する方法 | アフィリエイトJAPAN]。


* [https://senooken.jp/post/2020/02/21/3905/ CORESERVERでのFastCGI/CGI版PHPの利用手順 – senooken JP]
* [行動]-[サイトコンテンツ]-[全てのページ]
* [https://help.coreserver.jp/faq/php-fast-cgi/ FastCGI版PHP 各バージョンのPHP設定方法 | よくある質問 | サポート | レンタルサーバー CORESERVER(コアサーバー)]
* [表示する行数]=5000
* [https://help.coreserver.jp/faq/php-cgi/ PHPをCGIとして動かす方法を教えてください | よくある質問 | サポート | レンタルサーバー CORESERVER(コアサーバー)]
* [エクスポート]=TSV
* [https://engineer-milione.com/create/python-execution.html レンタルサーバー各社でのPythonの実行方法まとめ]


CORESERVERでのCGIの設定方法がある。
=== 流入元特定 ===
{| class="wikitable"
「[https://support.google.com/analytics/thread/252885536/%E4%BC%9A%E5%93%A1%E7%99%BB%E9%8C%B2%E7%94%BB%E9%9D%A2%E3%81%AE%E6%B5%81%E5%85%A5%E5%85%83%E6%8E%A2%E7%B4%A2%E6%96%B9%E6%B3%95%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6?hl=ja 会員登録画面の流入元探索方法について - Google アナリティクス コミュニティ]」どのページから会員登録があったか、会員登録に結びつく記事は非常に重要。<blockquote>こんにちは。
|+CORESERVERのFastCGI版PHPとCGI版PHPの設定方法
!項目
!FastCGI
!CGI
|-
|バージョンの変更
|管理画面
|<code>.htaccess</code>内の
<code>AddHandler application/x-httpd-phpcgiXX .php</code>
|-
|設定ディレクトリー
| colspan="2" rowspan="1" |<code>/virtual/<username>/public_html/.fast-cgi-bin/</code>
|-
|CGIの実行ファイル
|<code>phpXX.fcgi</code>
|<code>phpXX.cgi</code>
|-
|PHPの設定ファイル
|<code>phpXX.ini</code>
|<code>php.ini</code>
|-
|設定の反映タイミング
|バージョン切替時
|即時
|}
~/public_html/.fast-cgi-bin/のphpXX.fcgi phpXX.cgiがCGIの実行ファイル。このファイルか最後の行のexecのパスを変更すると、自前コマンドに変更可能。


FastCGIは管理画面からバージョンを変更したタイミングで反映される。ただ、ファイル拡張子が.phpじゃないとこのFastCGIが実行されない模様。
探索レポートでユーザーセグメントを作成する集計方法はいかがでしょうか。


CGIは.htaccessに以下の内容を記述してCGI板PHPのバージョンを指定する。
・自由形式レポートを作成
AddHandler application/x-httpd-phpcgiXX .php
cgiのファイルには実行権限が必要。
chmod +x py.py
拡張子がないとダメな模様。加えて、.htaccessに以下の記述。
AddHandler cgi-script .py
これでpy.pyで動作はする。


拡張子じゃなくてファイル名で実行したい場合、SetHandlerでしていする ([https://senooken.jp/post/2019/06/01/2333/ AddType, AddHandler, SetHandlerの違い – senooken JP])。
・セグメント作成 > ユーザーセグメント
<FilesMatch py$>
    SetHandler cgi-script
</FilesMatch>
これでpyでもアクセスできる。


FastCGI版の場合、以下のような設定でファイル名でマッチさせれば実行できそうな気もするが。
・条件は page_view > パラメータ page_location > 含む:会員登録画面のURL を指定
<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>
500
<FilesMatch gnusocial$>
        SetHandler application/x-httpd-php
</FilesMatch>
pythonがphpとして認識され、テキストがそのまま表示される。


SetHandler fcgid-scriptにしたらFastCGIで動作する。プログラムがFastCGI対応になっている必要がある。
・「会員登録画面閲覧ユーザー」などセグメント名をセットして保存
<FilesMatch gnusocial$>
        SetHandler fcgid-script
</FilesMatch>


== Analytics ==
・探索レポートにセグメントを適用


==== Exam ====
・ディメンション:セッションの参照元 / メディア、ランディング ページ + クエリ文字列
<nowiki>##</nowiki> About


<nowiki>https://gnusocial.jp/notice/4506679</nowiki>
・指標:セッション


<nowiki>###</nowiki> 全般
ご確認よろしくお願いいたします。


- マーケティング・ビジネス実務検定
※ページ閲覧の発生しなかったセッションはランディングページが (not set)になります。


- IMA検定
 開きっぱなしのタブから再訪問するセッションなどが該当します。ご参考までに。</blockquote>PMProでも似たような回答。<blockquote>Google Analytics 4 can track ecommerce conversions and then assign page value to posts that were a part of their conversion path for that engaged session. </blockquote>


- Web検定
== Server ==


- ネットマーケティング検定
=== httpd ===
Apache HTTP Server


<nowiki>###</nowiki> 解析系
==== About ====
httpdの利用可能な情報。


- ウェブ解析士
https://chatgpt.com/c/6761f851-df0c-800b-86e9-1624b458d66d
# 使用可能な指令一覧
apachectl -L
httpd -L
# 使用可能なモジュール一覧
apachectl -M
httpd -M
.htaccessで使用可能な指令の一覧。


- GAIQ
[https://senooken.jp/post/2019/04/19/2010/ .htaccessで使用可能な指令一覧 – senooken JP]


- 統計検定
==== Operation ====
サーバーの稼働や状態確認などで重要な操作がいくつかある。systemd前提。


- Webアナリスト検定
ログ・状態確認。
sudo systemctl status apache2
sudoをつけないと詳細ログを確認できない。
sudo systemctl restart apache2
sudo systemctl start apache2
sudo systemctl stop apache2


GAIQが無料だしどうせ使うからいいかな。
==== Access Control ====


<nowiki>https://wacul-ai.com/blog/access-analysis/google-analytics-method/gaiq/</nowiki>
* [https://httpd.apache.org/docs/2.4/en/howto/access.html Access Control - Apache HTTP Server Version 2.4]
* [https://httpd.apache.org/docs/2.4/en/howto/auth.html Authentication and Authorization - Apache HTTP Server Version 2.4]
* [https://httpd.apache.org/docs/2.4/ja/mod/mod_authz_core.html#logic mod_authz_core - Apache HTTP Server Version 2.4]


<nowiki>https://www.plan-b.co.jp/blog/seo/12792/</nowiki>
DoS攻撃対策などで重要な設定。


<nowiki>##</nowiki> URL
mod_authz_core/mod_authz_hostがコアモジュール。mod_rewriteも関係ある。


- <nowiki>https://ceres-inc.jp/business-tips/recommended-webmarketing-shikaku/</nowiki>
基本構文は以下。
Require host <address>
Require ip <ip address>
1番目の形式はドメイン名。2番目はIPアドレス。部分マッチする。マッチしたもののアクセスを許可する。


- <nowiki>https://mynavi-creator.jp/blog/article/qualification-for-web-marketer</nowiki>
Requireの直後にnotを指定してアクセス禁止にできる。こちらが重要。


- <nowiki>https://www.icloud.co.jp/article/exam/features-and-5-acquisition-benefits.html</nowiki>
==== mod_cgi ====
[https://httpd.apache.org/docs/current/en/mod/mod_cgi.html mod_cgi - Apache HTTP Server Version 2.4]


- <nowiki>https://digitor.jp/textbook/web-analytical-qualification/</nowiki>
CGIプロトコルのApacheモジュール。cgi-scriptにハンドラーを割り当てるとCGIとして扱う。


=== Tool ===
==== mod_fcgid ====
サイト分析用のツールがいくつかある ([https://hidesunblog.com/blog-ranking-sites/ 2023年ブログランキング!おすすめブログランキングサイト比較【一般人向け】])。
[https://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html mod_fcgid - Apache HTTP Server Version 2.5]


* SimilarWeb
FastCGIプロトコルのApacheモジュール。AddHandlerかSetHandlerでfcgid-scriptハンドラーに割り当てられると、FastCGIとして処理される。
* Ubersuggest
* ahrefs
* Googleキーワードプランナー


=== 閲覧数取得 ===
プログラム側もFastCGIに対応している必要がある。
出典: [https://affiliate-jpn.com/archives/5595 GoogleAnalyticsで自サイトの人気記事ランキングを表示する方法 | アフィリエイトJAPAN]。


* [行動]-[サイトコンテンツ]-[全てのページ]
==== Error ====
* [表示する行数]=5000
sudo systemctl status apache2
* [エクスポート]=TSV


=== 流入元特定 ===
● apache2.service - The Apache HTTP Server
[https://support.google.com/analytics/thread/252885536/%E4%BC%9A%E5%93%A1%E7%99%BB%E9%8C%B2%E7%94%BB%E9%9D%A2%E3%81%AE%E6%B5%81%E5%85%A5%E5%85%83%E6%8E%A2%E7%B4%A2%E6%96%B9%E6%B3%95%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6?hl=ja 会員登録画面の流入元探索方法について - Google アナリティクス コミュニティ]」どのページから会員登録があったか、会員登録に結びつく記事は非常に重要。<blockquote>こんにちは。
      Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
    Drop-In: /etc/systemd/system/apache2.service.d
              └─privatetmp.conf
      Active: failed (Result: exit-code) since Fri 2024-12-06 15:09:28 JST; 12s ago
        Docs: <nowiki>https://httpd.apache.org/docs/2.4/</nowiki>
    Process: 38461 ExecStart=/usr/sbin/apachectl start (code=exited, status=1/FAILURE)
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: AH00548: NameVirtualHost has no effect and will be removed in the next release /etc/apache2/ports.conf:8
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: [Fri Dec 06 15:09:28.259153 2024] [core:warn] [pid 38464] AH00117: Ignoring deprecated use of DefaultType in line 122 of /etc/apache2/apache2.conf.
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: AH00112: Warning: DocumentRoot [/home/gree/frontend/greenet/htdocs_net] does not exist
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: AH00526: Syntax error on line 7 of /etc/apache2/conf-available/rewrite-greenet.conf:
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: RewriteRule: unknown flag 'UnsafeAllow3F'
Dec 06 15:09:28 z-ken-senoo apachectl[38461]: Action 'start' failed.
Dec 06 15:09:28 z-ken-senoo apachectl[38461]: The Apache error log may have more information.
Dec 06 15:09:28 z-ken-senoo systemd[1]: apache2.service: Control process exited, code=exited, status=1/FAILURE
Dec 06 15:09:28 z-ken-senoo systemd[1]: apache2.service: Failed with result 'exit-code'.
Dec 06 15:09:28 z-ken-senoo systemd[1]: Failed to start The Apache HTTP Server.


探索レポートでユーザーセグメントを作成する集計方法はいかがでしょうか。
===== AH00548: NameVirtualHost has no effect and will be removed in the next release /etc/apache2/ports.conf:8 =====
NameVirtualHost指令が廃止予定なので、行を削除して対応する。


・自由形式レポートを作成
===== AH00117: Ignoring deprecated use of DefaultType in line 122 of /etc/apache2/apache2.conf. =====


・セグメント作成 > ユーザーセグメント
* Gentooの~amd64にApache 2.4.1が来たので試してみた https://meihong.work/computer/server-administration/apache/gentoo%E3%81%AEamd64%E3%81%ABapache-2-4-1%E3%81%8C%E6%9D%A5%E3%81%9F%E3%81%AE%E3%81%A7%E8%A9%A6%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/
* Upgrading to 2.4 from 2.2 https://httpd.apache.org/docs/2.4/upgrading.html
* DefaultType Directive https://httpd.apache.org/docs/2.4/en/mod/core.html#defaulttype


・条件は page_view > パラメータ page_location > 含む:会員登録画面のURL を指定
DefaultTypeはnone以外意味がなく、警告表示になる模様。


・「会員登録画面閲覧ユーザー」などセグメント名をセットして保存
==== .htaccess ====


・探索レポートにセグメントを適用
===== directive =====
[https://senooken.jp/post/2019/04/19/2010/ .htaccessで使用可能な指令一覧 – senooken JP]


・ディメンション:セッションの参照元 / メディア、ランディング ページ + クエリ文字列
.htaccessで使用不能なよく登場して誤解する指令を整理しておく。


・指標:セッション
* Alias
* ScriptAlias
* Directory/DirectoryMatch
* Location/LocationMatch
逆にOKなもの。
 
* Files/FilesMatch


ご確認よろしくお願いいたします。
=== E-mail ===
[[https://www.itti.jp/web-direction/spam-blacklist-release/ サーバーIPがブラックリストに載ってメール送信エラーになるのを解除する方法]]


※ページ閲覧の発生しなかったセッションはランディングページが (not set)になります。
MailHog: Go言語製のメールサーバーソフト。


 開きっぱなしのタブから再訪問するセッションなどが該当します。ご参考までに。</blockquote>PMProでも似たような回答。<blockquote>Google Analytics 4 can track ecommerce conversions and then assign page value to posts that were a part of their conversion path for that engaged session. </blockquote>
=== Debian ===


== Server ==
==== PHP8 ====
[How To Install PHP 8.0 on Debian 11/10/9 | ComputingForGeeks](<nowiki>https://computingforgeeks.com/how-to-install-php-on-debian-linux/</nowiki>)


=== httpd ===
Debian 11の場合、PHP 8には外部リポジトリーが必要なので追加する。
Apache HTTP Server


==== About ====
sudo apt update
httpdの利用可能な情報。


https://chatgpt.com/c/6761f851-df0c-800b-86e9-1624b458d66d
sudo apt install -y lsb-release ca-certificates apt-transport-https software-properties-common gnupg2
# 使用可能な指令一覧
apachectl -L
httpd -L
# 使用可能なモジュール一覧
apachectl -M
httpd -M
.htaccessで使用可能な指令の一覧。


[https://senooken.jp/post/2019/04/19/2010/ .htaccessで使用可能な指令一覧 – senooken JP]
PHPパッケージを追加する。


==== Operation ====
echo "deb <nowiki>https://packages.sury.org/php/</nowiki> $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/sury-php.list
サーバーの稼働や状態確認などで重要な操作がいくつかある。systemd前提。


ログ・状態確認。
wget -qO - <nowiki>https://packages.sury.org/php/apt.gpg</nowiki> | sudo apt-key add -
sudo systemctl status apache2
sudoをつけないと詳細ログを確認できない。
sudo systemctl restart apache2
sudo systemctl start apache2
sudo systemctl stop apache2


==== Access Control ====
sudo apt update


* [https://httpd.apache.org/docs/2.4/en/howto/access.html Access Control - Apache HTTP Server Version 2.4]
これでPHP8を参照できるので、インストールする。
* [https://httpd.apache.org/docs/2.4/en/howto/auth.html Authentication and Authorization - Apache HTTP Server Version 2.4]
* [https://httpd.apache.org/docs/2.4/ja/mod/mod_authz_core.html#logic mod_authz_core - Apache HTTP Server Version 2.4]


DoS攻撃対策などで重要な設定。
sudo apt install php8.2


mod_authz_core/mod_authz_hostがコアモジュール。mod_rewriteも関係ある。
[How to Switch between Multiple PHP Version on Debian 12/11/10 – TecAdmin](<nowiki>https://tecadmin.net/switch-between-multiple-php-version-on-debian/</nowiki>)


基本構文は以下。
インストールしたら、PHPのバージョンを切り替える。
Require host <address>
Require ip <ip address>
1番目の形式はドメイン名。2番目はIPアドレス。部分マッチする。マッチしたもののアクセスを許可する。


Requireの直後にnotを指定してアクセス禁止にできる。こちらが重要。
a2dismod php7.4


==== mod_cgi ====
a2enmod php8.2
[https://httpd.apache.org/docs/current/en/mod/mod_cgi.html mod_cgi - Apache HTTP Server Version 2.4]


CGIプロトコルのApacheモジュール。cgi-scriptにハンドラーを割り当てるとCGIとして扱う。
sudo systemctl restart apache2


==== mod_fcgid ====
php 8.2にするとこういうエラー。
[https://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html mod_fcgid - Apache HTTP Server Version 2.5]


FastCGIプロトコルのApacheモジュール。AddHandlerかSetHandlerでfcgid-scriptハンドラーに割り当てられると、FastCGIとして処理される。
[Sat Sep 02 11:31:02.558029 2023] [php:error] [pid 25644] [client 133.106.38.37:57181] PHP Fatal error:  Uncaught Error: Undefined constant "DB_DATAOBJECT_ERROR_NODATA" in /var/www/gnusocial/public/index.php:104\nStack trace:\n#0 [internal function]: handleError()\n#1 {main}\n  thrown in /var/www/gnusocial/public/index.php on line 104


プログラム側もFastCGIに対応している必要がある。
念のためdockerで起動を試みましたが、同じくトップ画面を開くと同じエラーになります。


==== Error ====
<<nowiki>https://notabug.org/gnusocialjp/gnusocial/src/main/docker/development</nowiki>> にDockerでの起動方法があります。`docker compose up -d` を実行するだけでlocalhostでアクセスできます。
sudo systemctl status apache2


● apache2.service - The Apache HTTP Server
私とあなたとの環境の違いを排除したいので、dockerのインストールだけ頑張って、それでdockerでも簡単に動作確認してくれませんか?
      Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
    Drop-In: /etc/systemd/system/apache2.service.d
              └─privatetmp.conf
      Active: failed (Result: exit-code) since Fri 2024-12-06 15:09:28 JST; 12s ago
        Docs: <nowiki>https://httpd.apache.org/docs/2.4/</nowiki>
    Process: 38461 ExecStart=/usr/sbin/apachectl start (code=exited, status=1/FAILURE)
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: AH00548: NameVirtualHost has no effect and will be removed in the next release /etc/apache2/ports.conf:8
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: [Fri Dec 06 15:09:28.259153 2024] [core:warn] [pid 38464] AH00117: Ignoring deprecated use of DefaultType in line 122 of /etc/apache2/apache2.conf.
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: AH00112: Warning: DocumentRoot [/home/gree/frontend/greenet/htdocs_net] does not exist
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: AH00526: Syntax error on line 7 of /etc/apache2/conf-available/rewrite-greenet.conf:
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: RewriteRule: unknown flag 'UnsafeAllow3F'
Dec 06 15:09:28 z-ken-senoo apachectl[38461]: Action 'start' failed.
Dec 06 15:09:28 z-ken-senoo apachectl[38461]: The Apache error log may have more information.
Dec 06 15:09:28 z-ken-senoo systemd[1]: apache2.service: Control process exited, code=exited, status=1/FAILURE
Dec 06 15:09:28 z-ken-senoo systemd[1]: apache2.service: Failed with result 'exit-code'.
Dec 06 15:09:28 z-ken-senoo systemd[1]: Failed to start The Apache HTTP Server.


===== AH00548: NameVirtualHost has no effect and will be removed in the next release /etc/apache2/ports.conf:8 =====
==== alternative ====
NameVirtualHost指令が廃止予定なので、行を削除して対応する。
Ref: [https://wiki.debian.org/DebianAlternatives DebianAlternatives - Debian Wiki].


===== AH00117: Ignoring deprecated use of DefaultType in line 122 of /etc/apache2/apache2.conf. =====
OS内でバージョン違いのプログラムを管理するための仕組みがある。それがupdate-alternativesコマンド。<syntaxhighlight lang="sh">
sudo update-alternatives --display vi
sudo update-alternatives --config vi
</syntaxhighlight>オプションとコマンド名を指定することで、現在の実体と更新ができる。


* Gentooの~amd64にApache 2.4.1が来たので試してみた https://meihong.work/computer/server-administration/apache/gentoo%E3%81%AEamd64%E3%81%ABapache-2-4-1%E3%81%8C%E6%9D%A5%E3%81%9F%E3%81%AE%E3%81%A7%E8%A9%A6%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/
=== XAMPP ===
* Upgrading to 2.4 from 2.2 https://httpd.apache.org/docs/2.4/upgrading.html
* DefaultType Directive https://httpd.apache.org/docs/2.4/en/mod/core.html#defaulttype


DefaultTypeはnone以外意味がなく、警告表示になる模様。
==== ポート番号変更 ====
[https://qiita.com/neneta0921/items/3c2f9ac8ea9b5bcfc6e6 Xamppでポート競合を防ぐ方法 #PHP - Qiita]


==== .htaccess ====
XAMPP Control PanelのConfigから変更可能。


===== directive =====
phpmyadminはConfigのphpmyadminで、Servers.portを追加する。
[https://senooken.jp/post/2019/04/19/2010/ .htaccessで使用可能な指令一覧 – senooken JP]


.htaccessで使用不能なよく登場して誤解する指令を整理しておく。
== Vim ==


* Alias
=== vimdiff ===
* ScriptAlias
[https://maku77.github.io/vim/file/vimdiff.html 2 つのファイルの差分を取る・マージする (vimdiff, vim -d) - まくまくVimノート]
* Directory/DirectoryMatch
* Location/LocationMatch
逆にOKなもの。


* Files/FilesMatch
vimのdiff機能。ファイル同士の差分のチェック、マージで簡易的に使える。


=== E-mail ===
==== diffモードで起動 ====
[[https://www.itti.jp/web-direction/spam-blacklist-release/ サーバーIPがブラックリストに載ってメール送信エラーになるのを解除する方法]]
vim -d <file1> <file2>
vimdiff <file1> <file2>


MailHog: Go言語製のメールサーバーソフト。
==== 起動中のdiffモード ====
:diffs[plit] <file> " 上下分割
:vert[ical] diffs[plit] <file> " 左右分割
:diffthis " バッファー同士


=== Debian ===
==== 移動 ====


==== PHP8 ====
* [c=前の差分に移動。
[How To Install PHP 8.0 on Debian 11/10/9 | ComputingForGeeks](<nowiki>https://computingforgeeks.com/how-to-install-php-on-debian-linux/</nowiki>)
* ]c=次の差分に移動。


Debian 11の場合、PHP 8には外部リポジトリーが必要なので追加する。
==== マージ ====


sudo apt update
* dp=diff put。自分の内容を片方に反映。
* do=diff obtain。自分の内容に片方を反映。


sudo apt install -y lsb-release ca-certificates apt-transport-https software-properties-common gnupg2
=== Other ===


PHPパッケージを追加する。
==== Async ====
https:/github.com/skywind3000/asyncrun.vim


echo "deb <nowiki>https://packages.sury.org/php/</nowiki> $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/sury-php.list
asyncrun.vimは1個のバックグラウンド処理しか対応していない。


wget -qO - <nowiki>https://packages.sury.org/php/apt.gpg</nowiki> | sudo apt-key add -
<nowiki>https://github.com/skywind3000/asyncrun.vim/issues/12</nowiki>


sudo apt update
vim-dispatchならいけるのか?


これでPHP8を参照できるので、インストールする。
==== Binary ====
[https://vim-jp.org/vim-users-jp/2010/03/21/Hack-133.html vim-jp » Hack #133: バイナリファイルを編集する]


sudo apt install php8.2
==== grep ====
非同期でgrepする方法。


[How to Switch between Multiple PHP Version on Debian 12/11/10 – TecAdmin](<nowiki>https://tecadmin.net/switch-between-multiple-php-version-on-debian/</nowiki>)
<nowiki>https://superuser.com/questions/861783/how-to-run-a-grep-in-vim-asynchronously</nowiki>


インストールしたら、PHPのバージョンを切り替える。
<nowiki>https://www.reddit.com/r/vim/comments/5ses2e/async_grep_in_vim_8/</nowiki>


a2dismod php7.4
Vim 8の非同期APIはプラグイン用。


a2enmod php8.2
<nowiki>*</nowiki> <nowiki>https://github.com/mhinz/vim-grepper</nowiki>


sudo systemctl restart apache2
<nowiki>*</nowiki> <nowiki>https://github.com/skywind3000/asyncrun.vim</nowiki>


php 8.2にするとこういうエラー。
<nowiki>*</nowiki> <nowiki>https://github.com/tpope/vim-dispatch</nowiki>


[Sat Sep 02 11:31:02.558029 2023] [php:error] [pid 25644] [client 133.106.38.37:57181] PHP Fatal error:  Uncaught Error: Undefined constant "DB_DATAOBJECT_ERROR_NODATA" in /var/www/gnusocial/public/index.php:104\nStack trace:\n#0 [internal function]: handleError()\n#1 {main}\n  thrown in /var/www/gnusocial/public/index.php on line 104
<nowiki>https://wonderwall.hatenablog.com/entry/2017/10/09/210000</nowiki>


念のためdockerで起動を試みましたが、同じくトップ画面を開くと同じエラーになります。
asyncrun.vimでやるのがよさそう。


<<nowiki>https://notabug.org/gnusocialjp/gnusocial/src/main/docker/development</nowiki>> にDockerでの起動方法があります。`docker compose up -d` を実行するだけでlocalhostでアクセスできます。
==== AnsiEsc ====
<nowiki>*</nowiki> https:/unix.stackexchange.com/questions/444226/how-to-make-vim-interpret-escaped-characters-as-colors


私とあなたとの環境の違いを排除したいので、dockerのインストールだけ頑張って、それでdockerでも簡単に動作確認してくれませんか?
<nowiki>*</nowiki> https:/superuser.com/questions/358409/how-can-i-tell-vim-to-show-ansi-escape-codes-properly


==== alternative ====
本家は太字に対応していないのでこちらがいいかな。
Ref: [https://wiki.debian.org/DebianAlternatives DebianAlternatives - Debian Wiki].


OS内でバージョン違いのプログラムを管理するための仕組みがある。それがupdate-alternativesコマンド。<syntaxhighlight lang="sh">
- https:/github.com/powerman/vim-plugin-AnsiEsc
sudo update-alternatives --display vi
sudo update-alternatives --config vi
</syntaxhighlight>オプションとコマンド名を指定することで、現在の実体と更新ができる。


=== XAMPP ===
ただし、こちらはgvimでクリック時にカーソル位置がずれる。


==== ポート番号変更 ====
=== program ===
[https://qiita.com/neneta0921/items/3c2f9ac8ea9b5bcfc6e6 Xamppでポート競合を防ぐ方法 #PHP - Qiita]


XAMPP Control PanelのConfigから変更可能。
==== C ====
[https://daisuzu.hatenablog.com/entry/2012/05/06/204019 ワシのVimプラグインは百八式まであるぞ - daisuzu's notes]


phpmyadminはConfigのphpmyadminで、Servers.portを追加する。
【C/C++】


== Vim ==
     87. a.vim


=== vimdiff ===
        C/C++のヘッダとソースを切り替えます。
[https://maku77.github.io/vim/file/vimdiff.html 2 つのファイルの差分を取る・マージする (vimdiff, vim -d) - まくまくVimノート]


vimのdiff機能。ファイル同士の差分のチェック、マージで簡易的に使える。
     88. c.vim


==== diffモードで起動 ====
        C/C++のテンプレートやイディオムの入力をサポートしてくれます。
vim -d <file1> <file2>
vimdiff <file1> <file2>


==== 起動中のdiffモード ====
     89. CCTree
:diffs[plit] <file> " 上下分割
:vert[ical] diffs[plit] <file> " 左右分割
:diffthis " バッファー同士


==== 移動 ====
        cscopeを使って関数のコールグラフを表示してくれます。


* [c=前の差分に移動。
     90. Source-Explorer-srcexpl.vim
* ]c=次の差分に移動。


==== マージ ====
        ソース解析ツール、Source InsightのVim版です。


* dp=diff put。自分の内容を片方に反映。
     91. trinity.vim
* do=diff obtain。自分の内容に片方を反映。


=== Other ===
        taglist, srcexpl, nerdtreeを同時に起動して


==== Async ====
        VimがIDE画面のような画面になります。
https:/github.com/skywind3000/asyncrun.vim


asyncrun.vimは1個のバックグラウンド処理しか対応していない。
     92. cscope-menu


<nowiki>https://github.com/skywind3000/asyncrun.vim/issues/12</nowiki>
        cscope用のメニューを表示してくれます。


vim-dispatchならいけるのか?
     93. gtags.vim


==== Binary ====
        gtagsを使ってファイルを開けます。
[https://vim-jp.org/vim-users-jp/2010/03/21/Hack-133.html vim-jp » Hack #133: バイナリファイルを編集する]


==== grep ====
     94. DoxygenToolkit.vim
非同期でgrepする方法。


<nowiki>https://superuser.com/questions/861783/how-to-run-a-grep-in-vim-asynchronously</nowiki>
        Doxygenコメントの入力をサポートしてくれます。


<nowiki>https://www.reddit.com/r/vim/comments/5ses2e/async_grep_in_vim_8/</nowiki>
== Visual Studio Code ==


Vim 8の非同期APIはプラグイン用。
=== Keybind ===


<nowiki>*</nowiki> <nowiki>https://github.com/mhinz/vim-grepper</nowiki>
==== 矩形選択 ====
Ref: [https://mitomito.hatenablog.jp/entry/2021/01/27/073000#:~:text=VS%20Code%E3%81%AE%E7%9F%A9%E5%BD%A2%E9%81%B8%E6%8A%9E%E3%81%A8%E7%9F%A9%E5%BD%A2%E8%B2%BC%E4%BB%98%E3%81%AE%E6%93%8D%E4%BD%9C%E6%96%B9%E6%B3%95%201%20%E3%83%9E%E3%82%A6%E3%82%B9%E3%81%A7%E6%93%8D%E4%BD%9C%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88%20shift%20%2B%20alt%20%2B,shift%20%2B%20alt%20%2B%20%E7%9F%A2%E5%8D%B0%E3%81%A7%E4%BB%BB%E6%84%8F%E3%81%AE%E7%AF%84%E5%9B%B2%E3%82%92%E9%81%B8%E6%8A%9E%E3%81%97%E3%80%81%20%28or%20%E5%88%87%E3%82%8A%E5%8F%96%E3%82%8A%29%E3%81%99%E3%82%8B%20 VS Codeの矩形選択と矩形貼付の操作方法 - mito’s blog].


<nowiki>*</nowiki> <nowiki>https://github.com/skywind3000/asyncrun.vim</nowiki>
* s-alt-クリック
* c-s-alt-矢印
ジャンプ


<nowiki>*</nowiki> <nowiki>https://github.com/tpope/vim-dispatch</nowiki>
* 括弧ジャンプ: C-S-\


<nowiki>https://wonderwall.hatenablog.com/entry/2017/10/09/210000</nowiki>
=== Config ===


asyncrun.vimでやるのがよさそう。
==== Default terminal ====
Ref: [https://stackoverflow.com/questions/44435697/change-the-default-terminal-in-visual-studio-code bash - Change the default terminal in Visual Studio Code - Stack Overflow].


==== AnsiEsc ====
[F1]-[Terminal: Select Default Profile]
<nowiki>*</nowiki> https:/unix.stackexchange.com/questions/444226/how-to-make-vim-interpret-escaped-characters-as-colors


<nowiki>*</nowiki> https:/superuser.com/questions/358409/how-can-i-tell-vim-to-show-ansi-escape-codes-properly
=== cscope ===
cscope用のプラグインが何個かある。


本家は太字に対応していないのでこちらがいいかな。
* [https://marketplace.visualstudio.com/items?itemName=xulion.codescope scope4code - Visual Studio Marketplace]
* [https://marketplace.visualstudio.com/items?itemName=SeungukShin.cscope-code cscope-code - Visual Studio Marketplace]


- https:/github.com/powerman/vim-plugin-AnsiEsc
scope4codeのほうがいろいろできそうだが、うまく動作しなかった。使い方がよくわからない。


ただし、こちらはgvimでクリック時にカーソル位置がずれる。
cscope-codeはシンプルだが動作した。こちらを当分使うことにする。


=== program ===
Macの場合、control-. sのように、control-.の後に、controlを話してsを押すと発動する。カーソル下のシンボルしか使えない感じなのがネック。まあいい。


==== C ====
=== Vim ===
[https://daisuzu.hatenablog.com/entry/2012/05/06/204019 ワシのVimプラグインは百八式まであるぞ - daisuzu's notes]


【C/C++】
* [https://marketplace.visualstudio.com/items?itemName=vscodevim.vim Vim - Visual Studio Marketplace]


     87. a.vim
VSCodedでVimのキー操作を使うためのプラグイン。これが一番人気。いや、Vimのエミューレーターは中途半端な感じだから使わないほうがいいかな。


        C/C++のヘッダとソースを切り替えます。
=== Extension ===
CSS


     88. c.vim
Tailwind CSS IntelliSense


        C/C++のテンプレートやイディオムの入力をサポートしてくれます。
==== PHP ====
Laravel Blade Snippets


     89. CCTree
===== PHP Intelephense =====
Ref: [https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense - Visual Studio Marketplace].


        cscopeを使って関数のコールグラフを表示してくれます。
VSCodeのPHPの補完拡張として人気が高い。


     90. Source-Explorer-srcexpl.vim
====== Quick Start ======
設置後、しておくべき設定がある。


        ソース解析ツール、Source InsightのVim版です。
* Go to <code>Extensions</code>.
* Search for <code>@builtin php</code>
* Disable <code>PHP Language Features</code>. Leave <code>PHP Language Basics</code> enabled for syntax highlighting.


     91. trinity.vim
VSCodeの [PHP Language Features] を無効にしておくとのこと。


        taglist, srcexpl, nerdtreeを同時に起動して
後は、.php以外の拡張子でPHPファイルがあれば、関連付けを追加するとか。


        VimがIDE画面のような画面になります。
====== Module ======
peclなどPHPの標準モジュールで一部認識できないものがある。


     92. cscope-menu
「[https://stackoverflow.com/questions/62258598/undefined-type-imagick-in-vscodes-intelephense php - Undefined type 'Imagick' in VSCode's intelephense - Stack Overflow]」にあるように、そういう場合は [Settings]-[Stubs] で追加するとよい。


        cscope用のメニューを表示してくれます。
====== Coding ======
Ref: [https://beyondjapan.com/blog/2020/02/intelephense-vscode-php/ VSCode で PHP 開発するならインテリセンス最強の intelephense を使おう | 株式会社ビヨンド].


     93. gtags.vim
intelephenseでコード補完を認識しやすい書き方というのがある。


        gtagsを使ってファイルを開けます。
まず、型をつけられるものはつける。<syntaxhighlight lang="php">
function superMethod()
{
    /** @var AwesomeService $awesomeService */
    $awesomeService = $this->app->make(AwesomeService::class);
    $awesomeService->awesomeMethod();
}
</syntaxhighlight>ローカル変数も型名を指定する。これをしないと、インスタンスでコード補完が効かない。


     94. DoxygenToolkit.vim
=== Other ===


        Doxygenコメントの入力をサポートしてくれます。
==== Remote ====
[https://www.mathkuro.com/vs-code/upload-and-download-remote-file/ 【WinSCPはもう不要?】VS Codeのダウンロード/アップロード機能が便利すぎる!! | マスクロドットコム]


== Visual Studio Code ==
[https://code.visualstudio.com/docs/remote/remote-overview Visual Studio Code Remote Development]


=== Keybind ===
公式拡張機能のVS Code Remote Developmentを使うと、リモートファイルをVS Codeで開いて、ドラッグドロップでファイル送受信ができるらしい。


==== 矩形選択 ====
== PhpStorm ==
Ref: [https://mitomito.hatenablog.jp/entry/2021/01/27/073000#:~:text=VS%20Code%E3%81%AE%E7%9F%A9%E5%BD%A2%E9%81%B8%E6%8A%9E%E3%81%A8%E7%9F%A9%E5%BD%A2%E8%B2%BC%E4%BB%98%E3%81%AE%E6%93%8D%E4%BD%9C%E6%96%B9%E6%B3%95%201%20%E3%83%9E%E3%82%A6%E3%82%B9%E3%81%A7%E6%93%8D%E4%BD%9C%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88%20shift%20%2B%20alt%20%2B,shift%20%2B%20alt%20%2B%20%E7%9F%A2%E5%8D%B0%E3%81%A7%E4%BB%BB%E6%84%8F%E3%81%AE%E7%AF%84%E5%9B%B2%E3%82%92%E9%81%B8%E6%8A%9E%E3%81%97%E3%80%81%20%28or%20%E5%88%87%E3%82%8A%E5%8F%96%E3%82%8A%29%E3%81%99%E3%82%8B%20 VS Codeの矩形選択と矩形貼付の操作方法 - mito’s blog].


* s-alt-クリック
=== Jump ===
* c-s-alt-矢印
ジャンプ


* 括弧ジャンプ: C-S-\
* https://chatgpt.com/c/6799c4ec-7660-800b-ad5d-fbc37e16a1a5
* [https://www.jetbrains.com/help/phpstorm/navigating-through-the-source-code.html#go_to_implementation Source code navigation | PhpStorm Documentation]


=== Config ===
includeなどで参照しているファイルパスのファイルを開く方法がいくつかある。


==== Default terminal ====
* C-b
Ref: [https://stackoverflow.com/questions/44435697/change-the-default-terminal-in-visual-studio-code bash - Change the default terminal in Visual Studio Code - Stack Overflow].
* C-LButton
* C-N/C-O でファイルを開いてファイルパスを貼り付け。


[F1]-[Terminal: Select Default Profile]
認識できないことがあるので3番目が汎用的。


=== cscope ===
=== Encoding ===
cscope用のプラグインが何個かある。


* [https://marketplace.visualstudio.com/items?itemName=xulion.codescope scope4code - Visual Studio Marketplace]
* [https://pleiades.io/help/phpstorm/encoding.html エンコード | PhpStorm ドキュメント]
* [https://marketplace.visualstudio.com/items?itemName=SeungukShin.cscope-code cscope-code - Visual Studio Marketplace]
* [https://pleiades.io/help/phpstorm/settings-file-encodings.html ファイルエンコーディング | PhpStorm ドキュメント]


scope4codeのほうがいろいろできそうだが、うまく動作しなかった。使い方がよくわからない。
パス単位で文字エンコーディングを設定可能。


cscope-codeはシンプルだが動作した。こちらを当分使うことにする。
[PhpStorm]-[Settings]-[Editor]-[File Encodings] から行う。


Macの場合、control-. sのように、control-.の後に、controlを話してsを押すと発動する。カーソル下のシンボルしか使えない感じなのがネック。まあいい。
=== Scratch ===
[https://qiita.com/endam/items/cc2c4c2aee8d382acd9e 【New Year Calendar】君はPhpStormのScratch機能を知っているか #NewYearCalendar - Qiita]


=== Vim ===
メモなどの一時ファイルの作成機能。


* [https://marketplace.visualstudio.com/items?itemName=vscodevim.vim Vim - Visual Studio Marketplace]
[File]-[New Scratch File] からファイル形式を選んで作る。困ったらMarkdownで良いだろう。


VSCodedでVimのキー操作を使うためのプラグイン。これが一番人気。いや、Vimのエミューレーターは中途半端な感じだから使わないほうがいいかな。
作成したScratchファイルは [Project]-[Scratches and Consoles]-[Scratches] に格納される。


=== Extension ===
=== 矩形選択 ===
CSS
[https://pleiades.io/help/phpstorm/multicursor.html#find-and-select-multiple-occurrences-of-a-string 複数のカーソルと選択範囲 | PhpStorm ドキュメント]


Tailwind CSS IntelliSense
方法がいくつかある。


==== PHP ====
* Cmd-Shift-8
Laravel Blade Snippets
* Option-Shift-Middle


===== PHP Intelephense =====
=== Git ===
Ref: [https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client PHP Intelephense - Visual Studio Marketplace].


VSCodeのPHPの補完拡張として人気が高い。
==== Gitツールウィンドウ ====
C-9か左下のGitマークを選ぶとGitツールウィンドウの表示になる。ブランチとコミットログが表示される。ここから右クリックを使ってブランチ間の比較などができたりする。


====== Quick Start ======
==== ブランチ比較 ====
設置後、しておくべき設定がある。


* Go to <code>Extensions</code>.
* [https://tech-blog.rakus.co.jp/entry/2017/09/14/112033 PhpStormで始めるGit生活 - RAKUS Developers Blog | ラクス エンジニアブログ]
* Search for <code>@builtin php</code>
* [https://pleiades.io/help/phpstorm/manage-branches.html#compare_branches Git ブランチの管理 | PhpStorm ドキュメント]
* Disable <code>PHP Language Features</code>. Leave <code>PHP Language Basics</code> enabled for syntax highlighting.


VSCodeの [PHP Language Features] を無効にしておくとのこと。
コードレビューなどでよく使うブランチ同士の比較。


後は、.php以外の拡張子でPHPファイルがあれば、関連付けを追加するとか。
まず現在ブランチを比較対象ブランチに変更しておく。


====== Module ======
[Git]-[Branches]-比較対象ブランチ-[Compare with]
peclなどPHPの標準モジュールで一部認識できないものがある。


「[https://stackoverflow.com/questions/62258598/undefined-type-imagick-in-vscodes-intelephense php - Undefined type 'Imagick' in VSCode's intelephense - Stack Overflow]」にあるように、そういう場合は [Settings]-[Stubs] で追加するとよい。
これで上下に画面分割して、それぞれのブランチで固有のコミットログの一覧が表示される。派生元と派生先があるならば、片方が空になる。違うブランチ同士のマージ用に、こういう作りになっていると思われる。


====== Coding ======
差分ファイル一覧を見るには、右側の変更ファイルペーンでC-aを選ぶ。変更のある全ファイルのリストが表示される。
Ref: [https://beyondjapan.com/blog/2020/02/intelephense-vscode-php/ VSCode で PHP 開発するならインテリセンス最強の intelephense を使おう | 株式会社ビヨンド].


intelephenseでコード補完を認識しやすい書き方というのがある。
他に、Gitツールウィンドウを開いて、コミットログで右クリック-[Compare with Local]を選ぶとローカルと対象コミットとの比較になる。これがわかりやすい。


まず、型をつけられるものはつける。<syntaxhighlight lang="php">
ただ、基本は現在ブランチか、現在のワーキングツリーとの比較になる。現在ブランチを変更しておくのが基本になる。そこだけ押さえておけば、まあなんとか使えそう。
function superMethod()
{
    /** @var AwesomeService $awesomeService */
    $awesomeService = $this->app->make(AwesomeService::class);
    $awesomeService->awesomeMethod();
}
</syntaxhighlight>ローカル変数も型名を指定する。これをしないと、インスタンスでコード補完が効かない。


=== Other ===
==== 元ファイルオープン ====
差分ビューで差分チェック中に、シンボルや型定義などの確認で元ファイルを開きたいことがある。ジャンプ方法がある。


==== Remote ====
左上の [Jump to Source C-Down] の鉛筆マークを選ぶ。これでエディター側で元ファイルを開ける。
[https://www.mathkuro.com/vs-code/upload-and-download-remote-file/ 【WinSCPはもう不要?】VS Codeのダウンロード/アップロード機能が便利すぎる!! | マスクロドットコム]


[https://code.visualstudio.com/docs/remote/remote-overview Visual Studio Code Remote Development]
==== サブディレクトリー ====


公式拡張機能のVS Code Remote Developmentを使うと、リモートファイルをVS Codeで開いて、ドラッグドロップでファイル送受信ができるらしい。
* https://chatgpt.com/c/67a330c3-3a9c-800b-b40f-ee80d09f9ec0
* [https://pleiades.io/help/phpstorm/settings-version-control-directory-mappings.html ディレクトリマッピング | PhpStorm ドキュメント]


== PhpStorm ==
PHPStormで親のGitリポジトリーの下に、子のGitリポジトリーのディレクトリーがある場合、親ディレクトリーのGitしか認識してくれない。


=== Jump ===
認識してくれる方法がある模様。


* https://chatgpt.com/c/6799c4ec-7660-800b-ad5d-fbc37e16a1a5
Gitのマルチリポジトリー機能を使うらしい。
* [https://www.jetbrains.com/help/phpstorm/navigating-through-the-source-code.html#go_to_implementation Source code navigation | PhpStorm Documentation]


includeなどで参照しているファイルパスのファイルを開く方法がいくつかある。
[Settings]-[Version Control]-[Directory Mappings]-[+]


* C-b
以下を選択して [OK] を選ぶ。
* C-LButton
* C-N/C-O でファイルを開いてファイルパスを貼り付け。


認識できないことがあるので3番目が汎用的。
* ◉Directory: Git子ディレクトリーのパス
* VCS: Git


=== Encoding ===
これで対象ディレクトリーを右クリックでGitを選ぶと良い模様。


* [https://pleiades.io/help/phpstorm/encoding.html エンコード | PhpStorm ドキュメント]
==== Blame ====
* [https://pleiades.io/help/phpstorm/settings-file-encodings.html ファイルエンコーディング | PhpStorm ドキュメント]
行番号のところを右クリック-[Annotate with Git Blame] で行単位の修正履歴を表示できる。


パス単位で文字エンコーディングを設定可能。
* Annotate Revision: 現在の変更コミットを表示。
* Annotate Previous Revision: 前回のコミットの表示。


[PhpStorm]-[Settings]-[Editor]-[File Encodings] から行う。
過去の修正履歴の調査で役立つだろう。


=== Scratch ===
=== Search ===
[https://qiita.com/endam/items/cc2c4c2aee8d382acd9e 【New Year Calendar】君はPhpStormのScratch機能を知っているか #NewYearCalendar - Qiita]
https://chatgpt.com/c/6798762a-2c2c-800b-8dab-4a7b8252fe7b


メモなどの一時ファイルの作成機能。
[https://cuore.jp/tec-blog/phpstorm%E3%81%AE%E4%BE%BF%E5%88%A9%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88%E3%82%AD%E3%83%BC%EF%BD%9E%E6%A4%9C%E7%B4%A2%E7%B7%A8%EF%BD%9E/ PhpStormの便利ショートカットキー~検索編~]


[File]-[New Scratch File] からファイル形式を選んで作る。困ったらMarkdownで良いだろう。
PHPStormでは検索がいくつかある。


作成したScratchファイルは [Project]-[Scratches and Consoles]-[Scratches] に格納される。
ファイル名検索


=== 矩形選択 ===
* Mac以外=C-N
[https://pleiades.io/help/phpstorm/multicursor.html#find-and-select-multiple-occurrences-of-a-string 複数のカーソルと選択範囲 | PhpStorm ドキュメント]
* Mac=C-O


方法がいくつかある。
スペース区切りでAND検索になる。パスを含めると、ディレクトリーも絞り込める。


* Cmd-Shift-8
Search Everywhere
* Option-Shift-Middle


=== Git ===
Shift2回押下。


==== Gitツールウィンドウ ====
* C-f: ファイルない検索。
C-9か左下のGitマークを選ぶとGitツールウィンドウの表示になる。ブランチとコミットログが表示される。ここから右クリックを使ってブランチ間の比較などができたりする。
* C-F: 全体検索。


==== ブランチ比較 ====
=== Other ===


* [https://tech-blog.rakus.co.jp/entry/2017/09/14/112033 PhpStormで始めるGit生活 - RAKUS Developers Blog | ラクス エンジニアブログ]
==== Window ====
* [https://pleiades.io/help/phpstorm/manage-branches.html#compare_branches Git ブランチの管理 | PhpStorm ドキュメント]
[https://pleiades.io/help/phpstorm/open-close-and-move-projects.html プロジェクトを開く、移動、閉じる | PhpStorm ドキュメント]


コードレビューなどでよく使うブランチ同士の比較。
ペーンを分離したり移動したりできる。


まず現在ブランチを比較対象ブランチに変更しておく。
ペーン右上[…]-[View Mode]-[Window] を選ぶと、別画面に分離できる。並列時に重宝する。


[Git]-[Branches]-比較対象ブランチ-[Compare with]
==== ディレクトリーの無視 ====
[https://pleiades.io/help/phpstorm/excluding-files-from-project.html 除外されたファイルとフォルダー | PhpStorm ドキュメント]


これで上下に画面分割して、それぞれのブランチで固有のコミットログの一覧が表示される。派生元と派生先があるならば、片方が空になる。違うブランチ同士のマージ用に、こういう作りになっていると思われる。
[https://dev.macha795.com/phpstorm-ignore-dir/ PhpStormでコーディングで使用しないディレクトリを除外してパフォーマンスを改善する | プロガジ.DEV]


差分ファイル一覧を見るには、右側の変更ファイルペーンでC-aを選ぶ。変更のある全ファイルのリストが表示される。
シンボリックリンクだったりして、同じファイルが違うパスで表示されることがあって困る。ディレクトリーを除外する。


他に、Gitツールウィンドウを開いて、コミットログで右クリック-[Compare with Local]を選ぶとローカルと対象コミットとの比較になる。これがわかりやすい。
右クリック-[Mark Directory as]-[Excluded] を選ぶ。


ただ、基本は現在ブランチか、現在のワーキングツリーとの比較になる。現在ブランチを変更しておくのが基本になる。そこだけ押さえておけば、まあなんとか使えそう。
==== Bookmark ====
[https://pleiades.io/help/phpstorm/bookmarks.html#bookmark-files-folders ブックマーク | PhpStorm ドキュメント]


==== サブディレクトリー ====
よく参照するコードの行・ファイル・ディレクトリー、をブックマークに登録して、迅速にアクセスできる。


* https://chatgpt.com/c/67a330c3-3a9c-800b-b40f-ee80d09f9ec0
# 左端のプロジェクトツールウィンドウ (C-1) で対象項目を右クリック-[Bookmarks]-[Add Bookmark]
* [https://pleiades.io/help/phpstorm/settings-version-control-directory-mappings.html ディレクトリマッピング | PhpStorm ドキュメント]
# [View]-[Tool Windows]-[Bookmarks] を選ぶと、、サイドバーにBookmarkのボタンが表示される。
 
PHPStormで親のGitリポジトリーの下に、子のGitリポジトリーのディレクトリーがある場合、親ディレクトリーのGitしか認識してくれない。
 
認識してくれる方法がある模様。
 
Gitのマルチリポジトリー機能を使うらしい。
 
[Settings]-[Version Control]-[Directory Mappings]-[+]
 
以下を選択して [OK] を選ぶ。
 
* ◉Directory: Git子ディレクトリーのパス
* VCS: Git


これで対象ディレクトリーを右クリックでGitを選ぶと良い模様。
==== Web Browsers and Preview ====
[https://pleiades.io/help/phpstorm/settings-tools-web-browsers.html ウェブブラウザーとプレビュー | PhpStorm ドキュメント]


=== Search ===
PHPファイルの編集時に、右上にプレビューボタンが表示されて邪魔。以下の設定で非表示にできる。
https://chatgpt.com/c/6798762a-2c2c-800b-8dab-4a7b8252fe7b


[https://cuore.jp/tec-blog/phpstorm%E3%81%AE%E4%BE%BF%E5%88%A9%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88%E3%82%AD%E3%83%BC%EF%BD%9E%E6%A4%9C%E7%B4%A2%E7%B7%A8%EF%BD%9E/ PhpStormの便利ショートカットキー~検索編~]
[Cmd-,]-[Settings]-[Tools]-[Web Browsers and Preview]-[Show browser popup in the editor]-[▫️For HTML files]
 
PHPStormでは検索がいくつかある。
 
ファイル名検索
 
* Mac以外=C-N
* Mac=C-O
 
スペース区切りでAND検索になる。パスを含めると、ディレクトリーも絞り込める。


Search Everywhere
==== ファイル差分 ====
[https://pleiades.io/help/phpstorm/differences-viewer.html#diff-merge-viewer ファイルの差分ビューアー | PhpStorm ドキュメント]


Shift2回押下。
ファイル差分の閲覧機能がある。


* C-f: ファイルない検索。
右クリック-[Compare with Clipboard]
* C-F: 全体検索。


=== Other ===
これが手っ取り早い。


==== Window ====
==== PEARの認識 ====
[https://pleiades.io/help/phpstorm/open-close-and-move-projects.html プロジェクトを開く、移動、閉じる | PhpStorm ドキュメント]
1 pear show-configでphp_dir (=/usr/share/php/) を確認する。


ペーンを分離したり移動したりできる。
2 このディレクトリーをローカルマシンに保存する (~/projectなど任意の場所)。既存プロジェクトの外に配置した方が都合良いだろう。


ペーン右上[]-[View Mode]-[Window] を選ぶと、別画面に分離できる。並列時に重宝する。
3 PHPStormの[Settings]-[PHP]-[include Path] で2で保存したディレクトリーを指定する。


==== ディレクトリーの無視 ====
==== .bashrc ====
[https://pleiades.io/help/phpstorm/excluding-files-from-project.html 除外されたファイルとフォルダー | PhpStorm ドキュメント]
[https://stackoverflow.com/questions/36592226/bashrc-not-sourced-on-intellij-ideas-terminal bash - .bashrc not sourced on Intellij IDEA's terminal - Stack Overflow]


[https://dev.macha795.com/phpstorm-ignore-dir/ PhpStormでコーディングで使用しないディレクトリを除外してパフォーマンスを改善する | プロガジ.DEV]
いくつかの理由で、IntelliJは標準ではBashを対話モードで起動しない。だから.bashrcを読み込まない。


シンボリックリンクだったりして、同じファイルが違うパスで表示されることがあって困る。ディレクトリーを除外する。
ただし、これは設定で変更可能。


右クリック-[Mark Directory as]-[Excluded] を選ぶ。
[Settings]-[Tools]-[Terminal]-[Shell path] に-iを追加する。だめなら、--loginとか。


==== Bookmark ====
==== 終端スペースの自動除去 ====
[https://pleiades.io/help/phpstorm/bookmarks.html#bookmark-files-folders ブックマーク | PhpStorm ドキュメント]
[https://stackoverflow.com/questions/40962197/phpstorm-removing-tabs-spaces-on-every-save PhpStorm removing tabs/spaces on every save - Stack Overflow]


よく参照するコードの行・ファイル・ディレクトリー、をブックマークに登録して、迅速にアクセスできる。
PhpStormでファイルを開いて保存すると、勝手に終端スペースを削除する。デフォルトでそういう設定になっている。


# 左端のプロジェクトツールウィンドウ (C-1) で対象項目を右クリック-[Bookmarks]-[Add Bookmark]
[Settings/Preferences]-[Editor]-[General]-[Remove trailing spaces]=on
# [View]-[Tool Windows]-[Bookmarks] を選ぶと、、サイドバーにBookmarkのボタンが表示される。


== PIM ==
== PIM ==

2025年4月15日 (火) 10:18時点における版

ソフトウェア開発作業全般

Other

ASCIIFlow: 画面構成図などの作成でテキストなので便利かもしれない。

Project

名簿付きの寄付

  • Vim: https://vim-jp.org/vimdoc-ja/sponsor.html
  • Vim (list): https://www.vim.org/sponsor/hall_of_honour.php
  • KDE: https://relate.kde.org/
  • KDE (list): https://relate.kde.org/civicrm/profile?gid=18&search=0
  • Conservancy (list): https://sfconservancy.org/sponsors/
  • Conservancy: https://sfconservancy.org/donate/

Kanboard

クローズ時に自動移動

[Configure project]-[Automatic actions]

  • action=[Move the task to another project]
  • Event name=Closing a task
  • Column=Done
  • Project=

これでDoneをclose時にアーカイブ用のプロジェクトに移動できる。

Communication

Skype

すべてのエモーティコンのリストはありますか? - Microsoft サポート

Skyepで使用可能な絵文字の一覧。

Slack

チャンネル

https://slack.com/intl/ja-jp/help/articles/205239967-%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%AB%E3%81%AB%E5%8F%82%E5%8A%A0%E3%81%99%E3%82%8B

一覧表示

[ホーム]-[チャンネル]-[管理する]-[チャンネル一覧] でチャンネル一覧を閲覧可能。

パーマリンク

Slackの投稿パーマリンクをWebブラウザーで開くと、該当箇所にジャンプできない。デスクトップアプリがあると開ける。それでしのぐ。

JIRA

関連チケット

[修正するバージョン]/[影響するバージョン] のリンクをクリックすると、関連するissueが一覧表示される。これで未クローズチケットを確認するといい。

Confluence

ページの中で、 [作成] を選んでページを作ると、階層が勝手にできて、子ページへのリンクもできる。

ショートカットキー

キーボード ショートカット

https://ja.confluence.atlassian.com/doc/keyboard-shortcuts-139456.html

エディタ

ブロック フォーマット

Windows 操作 Mac
Ctrl + 0 Paragraph ⌘+ 0
Ctrl+ (1 ~ 6) (選択した番号の)見出しレベル ⌘+ (1—6)
Ctrl + 7 Preformatted ⌘+ 7
Ctrl + 8 Quote ⌘+ 8
Ctrl + Shift + B、または

* + Space

箇条書きリストを追加 ⌘ + Shift + B、または

* + Space

Ctrl + Shift + N、または

# + space

番号付きリストを追加 ⌘ + Shift + N、または

# + space

Ctrl + Shift + S Strikethrough ⌘ + Shift + S
Ctrl + Shift + Subscript ⌘ + Shift + ,
Ctrl + Shift + Superscript ⌘ + Shift + .
Ctrl + Shift + M Monospace ⌘ + Shift + M
Ctrl + \ Clear formatting ⌘ + \

豊富なフォーマット

CTRL + Shift + V

サファリのみ:Ctrl + Shift + Alt + V

書式設定なしでテキストを貼り付け ⌘ + Shift + V

Safari のみ:⌘ + Shift + Option + V

Ctrl+M Files and images ⌘+ M
Ctrl+K リンク([リンクの挿入] ダイアログが開く) ⌘ + K
Ctrl + Shift + D マークアップを挿入([マークアップの挿入] ダイアログが開く) ⌘ + Shift + D
Ctrl+Shift+A マクロ([マクロの選択] ダイアログが開く) ⌘ + Shift + A
Ctrl + Shift + O 次のインライン コメントに切り替え ⌘ + Shift + O
Ctrl + Shift + L 前のインライン コメントに切り替え ⌘ + Shift + L
CTRL + Shift + Z インライン コメントを閉じる ⌘ + Shift + Z
Ctrl + Shift + I ⌘ + Shift + I
Alt + 上矢印 行を上に挿入 Alt + 上矢印
Alt + 下矢印 下に行を挿入 Alt + 下矢印
Ctrl + Shift + X 行を切り取り ⌘ + Shift + X
Ctrl + Shift + C 行をコピー ⌘ + Shift + C
Ctrl + Shift + Y 行を上に貼り付け ⌘ + Shift + Y
Ctrl + Shift + ; 絵文字メニュー ⌘ + Shift + ;
CTRL + Shift + V 書式設定なしで貼り付け ⌘ + Shift + V
書式設定なしで貼り付け (Safari) ⌘ + Shift + Option + V
オートコンプリート

[] が勝手にリンクになるのが困る。

リンク、ファイル、マクロ、メンション、絵文字のオートコンプリート

https://ja.confluence.atlassian.com/doc/autocomplete-for-links-files-macros-mentions-and-emojis-249858190.html

オートコンプリートの無効化方法。

プロフィール画像を選択-[設定]-[エディター]-[☑️オートコンプリートの無効化]

ただ、オートコンプリートの丸ごと無効化は、便利な機能がなくなるので不味い。

一時的に回避したい場合、[の直前に何か文字があれば解釈されない。スペース開けて[があるとオートコンプリート扱いになる。


書式なしペースト

Confluenceで書式なしペースト(Ctrl+Shift+V)を有効にする #Confluence - Qiita [?]-[キーボードショートカット]-[General]-[▫️Enable General Shortcuts] にしてオフにすると有効になる。 [表の上部にペースト] と競合していたらしい。

マクロ

マクロ | Confluence Data Center 9.2 | アトラシアン製品ドキュメント

いくつか有用なマクロがある。

Other

パーマリンク

The Differences Between Various URL Formats for a Confluence Page | Confluence | Atlassian Documentation

Confluenceのページ新規作成時、パーマリンクが自動生成される。規則がある。

以下の条件にマッチしたら、padeId URLになる。それ以外は、タイトル名のURLになる。

  • [% & ? / ¥ ; " + :] などのようなURLの予約文字。
  • 非ラテン文字。
  • ページタイトル末尾が英数字以外の場合。
ページ履歴

ページ右上のメニュー-[ページ履歴]から履歴を確認できる。差分も確認できる。

ページ移動

ページの移動と順序の変更 | Confluence Data Center 9.2 | アトラシアン製品ドキュメント

ページ右上のメニュー-[移動]

Tool

General

Call tree

kcachegrindだったかな。

kscopeもこれか。

Doxygen+GraphVizで関数コールグラフ

kscope

https:/github.com/ivan0124/Linux-programming/wiki/How-to-use-KScope-to-trace-code

https:/sourceforge.net/projects/kscope/

http:/www.lemis.com/grog/software/kscope.php

cscope

cbrowser/kbrowserというGUIもある。

cscopeの大文字小文字無視検索

http://vim.1045645.n5.nabble.com/how-to-search-with-cscope-ignoring-case-td5715043.html

DBを別にする必要がありそう。

expect

端末の手動操作を自動化するソフト。

* ^と$は使えない。代わりに、\nを使う。

* 文字列の囲みに一重引用符 (') は使えない。二重引用符 (") のみ有効。

* expect文はawkみたいな感じ。

* ただし、expectは注意が必要。最初のexpectにマッチしないと先に進めない。タイムアウトとかするしかない。

expect -c "set timeout 5; spawn cat cat.txt; expect \nFAIL {send pwd/n; expect :; exit}"

https:/linuxjm.osdn.jp/html/expect/man1/expect.1.html

```

sh -eux <<-"EOT"

expect -c "set timeout 5; spawn ssh senooken@senooken-linux; expect :; send ieneko/n; expect aho {send echo aho} +x {send pwd/n}; expect /$; exit"

expect -c "set timeout 5; spawn ssh senooken@senooken-linux; expect :; send ieneko/n; expect + {send pwd/n}; expect /$; exit"

expect -c "set timeout 5; spawn cat cat.txt; expect \nFAIL {send pwd/n; expect :; exit}"

expect -c 'set timeout 10; spawn cat cat.txt; expect "aa F" {set AAA "abc"}; expect FAIL {send "$AAA/n"; expect " "; exit}'

EOT

```

GNU screen

GNU Screenコマンドをつかってみる #screen - Qiita

screenコマンド実行後に、C-a押下後に対応するキーを押して各種操作を実行する。

キー操作以外に、コマンドも用意されている。C-a :でコマンドラインモードに入る。

特に重要な操作。

  • Help
    • C-a ?
    • Command:help
  • Window
    • C-a c/C-a C/Command:screen=Windowを生成。
    • C-a space/C-a n/C-a C-n/Command:next=次のWindowへ移動。
    • C-a p/C-a C-p/C-a C-h/C-a Backspace/Command:prev=前のWindowへ移動。
  • 画面分割: Regionを分割してそこにWindowを割り当てる。
    • C-a S=横分割
    • C-a |=縦分割
    • C-a TAB/Command:focus=分割画面の移動。
  • クローズ
    • C-a X/Command:remove=現在のRegionを終了。
    • C-a Q/Command:Only=現在以外のRegionを終了。
.screenrc
スタートアップメッセージ
startup_message off
スクロール

linux screen中にマウスホイールでスクロールする方法 - 技術メモ集

デフォルトだとマウススクロールなどに対応していない。以下の設定で対応でき、通常使用で問題なくなる。

termcapinfo xterm* ti@:te@
defscrollback 100000

Binary

.so

ソフトウェアの依存関係などの調査で.soファイルの分析を行うことがある。

.soファイルの中のシンボル探し

  • nm
  • ldd
  • string

Diff

差分確認ツール。コードレビューなどで重要。

About

Macが鬼門。

M1 Macで使用可能なものの選択肢が極端に狭い。

https://chatgpt.com/c/678e249e-84f0-800b-b8da-7385d9aaf819

name OS Free GUI directory image comment
FileMerge Mac x x x Xcode付属ツール。悪くない。が、Mac専用。
P4Merge x x x - x ディレクトリー比較ができないのが惜しい。
DiffMerge x x x x - 悪くない。が開発停止。MacはIntel版のみ。
WinMerge Windows x x x 使いやすい。
Meld Windows/Linux x x x Linux系の標準。悪くない。
kdiff3 Windows/Linux x x x 開発停止。使えなくはない。
vimdiff x x x x - 使いにくい。
Visual Studio Code x x x x x ディレクトリー比較は [Compare Folders - Visual Studio Marketplace] 拡張機能。 画像比較は [Image Preview] らしい。
Intellij IDARE x - x x x
Beyond Compare x - x x x
DiffImg Windows/Linux x x x
PerceptuallDiff x - x
PixelCompare x x

DiffMerge一択になる。ファイルサイズも小さい。大きくても11 MB。

Visual Studio Codeが汎用的だから、こちらでいいかもしれない。

DiffMerge

mac で WinMerge |東京 AI 研究所

FileMerge

Mac純正のファイル差分確認ツール「FileMerge」が使いやすい - Reasonable Code

[/Applications/Xcode.app]-右クリック-[Show content]-[Contents/Applications/FileMerge.app]

コマンドラインからだとopendiff。

Visual Studio Code

About

ディレクトリー比較は [Compare Folders - Visual Studio Marketplace] 拡張機能。 画像比較は [Image Preview] らしい。

VSCode | 2つのファイルの内容を比較して差分を表示する

code -d <file1> <file2>

上記コマンドで差分表示できる。外部の差分ツールとして使う際は、上記コマンドになるように指定する。

GUIからだと、[View]-[Command Pallete]-[Compare] から比較できる。

比較のモードがいくつかある (VS Codeでファイル・ソースコードの差分を比較(diff)する2通りの方法)。

No. 比較モード 用途
1 ファイル: アクティブ ファイルを比較しています...

File: Compare Active File With...

現在のアクティブファイル と 指定したファイル を比較する。
2 ファイル: クリップボードとアクティブ ファイルを比較

File: Compare Active File with Clipboard

Ctrl + Cでクリップボードに保存された文字列 と 現在のアクティブファイル を比較する。
3 ファイル: 新しい無題のテキスト ファイルの比較

File: Compare New Untitled Text Files

比較モードで新規テキストファイルを2つ開いた状態となる。
4 ファイル: 保存済みファイルと作業中のファイルを比較

File: Compare Active File with Saved

未編集状態のアクティブファイル と 前回保存したアクティブファイル を比較する。
5 マージの場合: 現在の競合を比較

Merge Conflict: Compare Current Conflict

Git環境でブランチをマージした時にコンリクト(競合)が発生していないか比較する。

File: Compare Active File Withが素直か。

Diff Folders

VSCode拡張機能「Diff Folders」でフォルダ間の違いを簡単に比較しよう! | UNTIC | Web担当者のための仕事メディア

Diff Foldersの他に、Compare Foldersというのもある。が、Diff Foldersのほうが直感的で使いやすいらしい (is there a compare folders feature in VS Code? - Stack Overflow)。ただ、Compare Foldersのほうがダウンロード数が多い。

標準ではディレクトリー比較はできない。Diff Foldersの拡張機能が必要。

  1. Diff Foldersをインストール
  2. c-P-[Diff Folders]-[New Diff Panel] またはc-L
Compare Folders

VSCodeでフォルダ丸ごと比較する

Coding

タイムゾーン

タイムゾーン呪いの書 #timezone - Qiita

3文字形式は避けたほうが無難。

タイムゾーン名で判定する実装があるので、UTC-9なども避けたほうがいい。

tz databaseのAsia/Tokyoなどの確実性が高い。

Regular Expression

正規表現。重要。覚えにくいが重要なものをメモしておく。

後ろからマッチ。cが置換対象。

Case

/[^c]*$/: cより右端

マッチの前後の挿入

https:/vim.fandom.com/wiki/Power_of_g

:g/GST_.*("/s/^/LOG(INFO) << "DEBUG";/r/

行頭・行末で引っ掛ける。

関数にログ
:%s/([^")]*)/) /([a-z]* /)*{/&/rLOG(INFO) << "/1";/r/g

考慮するケース

double currentTime() const override { return m_element->currentTime(); }

glob

重要。正規表現とは似ているが異なる、パターンマッチング記法 (Pattern Matching Notation)。主に、globで採用されており、ディレクトリー・ファイルのマッチングで使われる。

使用可能な記号は以下3個。以下の3文字は\でエスケープできる。

  • ?: 任意の1文字にマッチ。
  • *: 任意の0以上の文字にマッチ。
  • [: []内の1文字にマッチ。正規表現の各括弧と同じ。ただし、先頭の否定が^ではなく、!。

ファイル名マッチ時には、追加で特殊なルールがある。

.から始まるファイル名へのマッチには、.が必要。つまり、*?は先頭の.にはマッチしない。[!a] のような否定形の各括弧記法も.にはマッチしない。加えて、先頭の[.]もマッチするかは不定(unspecified)。

globで.ファイルを含めたい場合、工夫が必要 (PHP: glob - Manual)。

.[!.]* *

上記のように.ファイルのマッチとそれ以外を指定する必要がある。

.[!.]* は、...以外の..始まりのファイルにマッチする。

.*を指定すると、./..がマッチするので注意する。最近のシェルは、シェル側で気を利かせているようで、.*だと. /..はマッチしない。

引用符のネスト

シェルやプログラミング言語で、文字列リテラルの表現などで、一重引用符'と二重引用符"を使う。

JSON作成や変数展開などで、これらをネストさせたいことがある。その基本的な考え方を整理する。

交互にしていい場合は簡単二重。引用符内に一重引用符を配置、一重引用符内に二重引用符を配置すればいい。

問題はこれがNGな場合。特にありがちなのが、JSONの生成。JSONの引用符は二重引用符のみ。一重引用符の中だと、二重引用符の変数展開が使用不能。外側を二重引用符にする必要がある。

二重引用符は、内部で変数展開が可能。この都合で、バックスラッシュ\によるエスケープが有効。

基本的な方法。

  1. 既存の一重/二重引用符などをバックスラッシュでエスケープ。
  2. 全体を一重/二重引用符で囲む。

何かAwkの本か何かで、基本的な考え方の説明の記載があった気がする。

[{"ke\y":"valu\e"}] を例として考える。

  1. {"ke\y":"valu\e"}
  2. エスケープ: {\"ke\\y\":\"valu\\e\"}
  3. 全体囲み: "{\"ke\\y\":\"valu\\e\"}"

これでOK。また何か考慮不足があればそのときに考える。

ただ、元データに修正が必要なので、そのまま行きたい。ヒアドキュメント的なものが使えるならそれを使うのがいい。

例えば、シェルなら、catコマンドとコマンド置換で生テキストを使える。

echo $(cat <<-'EOT'
{"ke\y":"valu\e"}
EOT
)

.envなどで使える技?いや使えない。.envではシンプルなコマンドしか使えず、ヒアドキュメントは使えない模様。

JSONのvalue部分に適用したい場合。データの二重引用符をバックスラッシュでエスケープする。これはこうするしかない。JSONが二重引用符しか認めないから。

基本的な考え方がある。

  1. JSON value用に二重引用符"を\"で置換。
  2. \"がPHP/JavaScriptで二重引用符に扱いにならないように、\を\\に置換。
  3. JSON項目の二重引用符"を\"で置換。
  4. 全体を二重引用符"で囲む。

こういう感じ。JSONはawkでも任意の最終データで考える。途中にプログラミング言語でのパースがあるので、それを考慮する必要がある。

ケース変換

javascript - camelCase to kebab-case - Stack Overflow

キャメルケースをチェインケースにしたり、逆にしたりなどケース変換したいことがある。正規表現を駆使して実現する。

encode

【PHP入門】URLエンコードする方法(urlencode) | 侍エンジニアブログ

日本語や記号を他のコードに変換 (エンコード) する方式が何通りかある。把握しておくと役立つ。

  • パーセントエンコーディング/URLエンコード: URLで使用不能な文字を%16進数で連結。
  • UTF-8
  • base64: 全データを「A-Z」「a-z」「0-9」「+」「/」の64文字で表現。文末に=を使うので実質は65文字。
  • HTMLエンコード: HTMLで特殊な意味を持つ文字を&lt;などに変換する。

Percent-encoding

unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"

上記文字はエンコードの対象外。

英数変換

string - PHP How to encode all characters with rawurlencode - Stack Overflow

変数名への変換などで、日本語や記号を英数字 [0-9a-zA-Z] に変換したいことがある。

こういう目的だと%エンコーディングが適している。

ただし、一部の記号を許可しているので、自前で変換する。

function encode_all($str) {
    $hex = unpack('H*', $str);
    return preg_replace('~..~', '%$0', strtoupper($hex[1]));
}

$str = 'big ƒüßchen';
print_r(encode_all($str));

Term

紛らわしい用語がある。

フレームワークの中にライブラリーも含めていいと思う。

Pythonのモジュールとパッケージとライブラリとフレームワークの違い」がわかりやすい。

フレームワークはライブラリーを含んでいる。ライブラリーで共通でいいと思う。

Category

ソフトウェア開発工程 - Wikipedia

ソフトウェアの分類、ページ分類時に役立つ。

  • 言語
  • ツール: 静的解析、テスト、文書など。
  • フレームワーク

MediaWikiのページ名は全体で固有が条件なので、言語名+分類名でページを作るといい。

  • PHP language
  • PHP tool
  • PHP framework

成功時連続継続処理

一度の取得件数の上限が決まっていて、終了・失敗するまで取得を継続したいという処理がそれなりに発生する。

  1. 処理実行。
  2. 成功ならA、失敗なら終了。
  3. 処理実行。
  4. 成功ならA、失敗なら終了。

こういうパターン。いくつか実装方法があるが、while (true) のパターンが重複がなくてベストだと思う。

        /*
        // 無限ループで終了条件でブレイク
        while (true) {
            // 処理実行
            if (失敗) {
                break;
            }
            成功時処理
        }
        
        // do while
        do {
            処理実行
            if (成功時) {}            
        } while ();

        // for (初期化; 継続判定・終了判定; 成功時式) {
            処理実行
        }
        */

do-whileは成功・終了判定を2回書く必要がある。

forだと成功処理を式でしか書けない。成功処理を関数や即時実行関数式などで書くなら悪くはないし、ベストになりえる。

いや、成功時処理内の処理の結果次第で反復の終了条件などが追加で入るならNGになる。なので、やっぱりwhile(true)が無難。コード行数もそんなに変わらない。

これにさらに初回だけ、ヘッダーの取得、書き込み処理などが発生する場合、初回だけループの外でやるのがきれいだろうか?初回処理が2回登場することになるけれど。

offsetなどで初回の判定が反復内でできるから、それで分けるのがいいか?

        $offset = 0;
        while (true) {
            $currentReturnCode = $service->sendRequest(Raku2Config::API_TYPE_CSV_EXPORT, Raku2Config::CONFIG_API_URL_MULTI_API, [
                json_encode([
                    'dbSchemaId' => $table_info['dbSchemaId'],
                    'offset' => $offset,
                    'limit' => $limit,
                ])
            ]);

            $response = $service->getApiResultJson();
            // 終了条件: 戻り値が成功以外、か応答本体が1行 (ヘッダーのみ) の時。
            if (($currentReturnCode !== Raku2Config::EXIT_SUCCESS) || (substr_count($response, "\n") <= 1)) break;

            // 2回目からはヘッダー除去して書き込み。
            $start = strpos($response, "\n") + 1;
            $flat = FILE_APPEND;
            if ($offset === 0) {
                $start = $flag = 0;
                $path = stream_get_meta_data($fp = tmpfile())['uri'];
            }
            file_put_contents($path, substr($response, $start), $flag);
            $offset += $limit;
            sleep(3);
        }
        for ($offset = 0;
            ($currentReturnCode === Raku2Config::EXIT_SUCCESS) && (substr_count($response, "\n") > 1);
            (function() use (&$offset, $limit, $response) {
                // 2回目からはヘッダー除去して書き込み。
                $start = strpos($response, "\n") + 1;
                $flag = FILE_APPEND;
                if ($offset === 0) {
                    $start = $flag = 0;
                    $path = stream_get_meta_data($fp = tmpfile())['uri'];
                }
                file_put_contents($path, substr($response, $start), $flag);
                $offset += $limit;
                sleep(3);
            })()
        ) {
            $currentReturnCode = $service->sendRequest(Raku2Config::API_TYPE_CSV_EXPORT, Raku2Config::CONFIG_API_URL_MULTI_API, [
                json_encode([
                    'dbSchemaId' => $table_info['dbSchemaId'],
                    'offset' => $offset,
                    'limit' => $limit,
                ])
            ]);
            $response = $service->getApiResultJson();
        }

character

BOM

UTF-8のBOM

\xef\xbb\xbf

この文字を先頭につけるとUTF-8のBOMになる。

Convert

IP/CIDR

// JavaScript
    /**
     * サブネットマスクをIPアドレス形式 (x.x.x.x/255.255.255.0) からCIDR形式 (x.x.x.x/24) に変換する。
     * @param {string} ipaddress - IPアドレス文字列 (x.x.x.x/x.x.x.x形式)。
     */
    toCIDR(ipaddress) {
      const [address, mask] = ipaddress.split('/')
      const segments = mask.split('.')
      const CIDR = segments
        .map((e) => Number(e).toString(2))
        .join('')
        .replace(/0*$/, '').length
      return address + '/' + CIDR
    },
    /**
     * サブネットマスクのCIDR形式 (24) をIPアドレス形式 (255.255.255.0)に変換する。
     * @param {number} cidr - ciderの数字。
     * @return {string} x.x.x.x形式のIPアドレス文字列。
     */
    cidrToIp(cidr) {
      const digit = 32
      const ip = ('1'.repeat(cidr) + '0'.repeat(digit)).substr(0, digit)
      return ip
        .match(/.{8}/g)
        .map((e) => parseInt(e, 2))
        .join('.')
    },

Algorithm

再帰処理

https://chatgpt.com/c/673d9bfe-2414-800b-9922-f94be6dbe950

配列の配列、オブジェクトのオブジェクトなど、再帰的な構造はけっこう遭遇する。

再帰関数で実装するほかに、スタックで処理する方法がある。

再帰関数のほうが簡単に実装できるが、関数呼び出しのオーバーヘッドがある。ネスト10-100程度くらいなら問題ない。

パフォーマンスや再帰中の細かい制御が必要なら、スタックが有利。ただし、実装がやや複雑。

最初は再帰関数で実装して、後でボトルネックになったらスタックというのも手。

https://chatgpt.com/c/6745228f-8b20-800b-8a41-bdaece8c03f5

再帰関数とスタックの他に、JSONなどの文字列にシリアライズして、文字列処理で対応するという手もある。

JSONPath/XPathなどの方法もあるが、基本的には外部ライブラリーが必要。

シンプルなケース以外は、再帰関数で処理したほうが結局シンプルな感じがする。

Other

コメントの著者名

https://chatgpt.com/c/67469d8d-7e64-800b-b82d-8c74f4e13c08

GNU socialのソースコードのコメントに著者名が大量にあった鬱陶しい。

大規模プロジェクトになると、編集者が膨大になる。VCSに任せて、本文には記載しなくていいと思う。

git blameで行単位で編集者が分かる。

UML

Tool

https://chatgpt.com/c/67441feb-d004-800b-96fd-0d9b04ffc628

What are the best UML tools for macOS? - Quora

  • デスクトップ
    • StarUML
    • ArgoUML
    • UMLet
    • OmniGraffle
    • edraw: 有料。
    • Umbrello
    • Modelio
  • クラウド
    • Visual Paradigm
    • Lucidchart: 有料。
    • Creately: 有料。
    • diagrams.net: モデルじゃない。
  • その他
    • PlantUML

UmbrelloとModelioはそれらと比較して何がよかったのだっけ?

Eclipse Papyrusが動作するならこれがいい。Eclipseは安定しているから、これのプラグインで動作するなら信頼できるだろう。

papyrusは一度試してダメだった気がするが。

クラス図

A=自分 (矢印の元)。B=相手 (矢印の先)

  • 継承関係
    • 汎化 (generalization): 実線白矢印。継承。
    • 実現 (realization): 点線矢印。interfaceの継承。
  • プロパティー単位
    • 関連 (association): 実線。あるクラスが他のクラスのインスタンスを持つ。ただし、所有までいかない。コンストラクターのDIも含む。人と車のように全体-部分の関係がない場合これ。困ったらこれでもいい。
    • 集約 (aggregation): 白菱形実線。関連の特殊系。所有者の方が菱形。所有される側は線。全体-部分の関係。ただし、部分は他の全体からも共有可能。List<T>やSet<T>のメンバー変数があれば集約の可能性が高い。
    • コンポジション (composition): 黒ひし形。子が単体で存在できない場合。親と生存期間が同一の場合。部分が他から共有されない。集約の特殊系。
    • リンク (link): 実線。クラスのインスタンス間の関係。クラス図ではなく、オブジェクト図で使われる。
  • メソッド単位
    • 依存 (dependency): 点線矢印。引数か返却値に使っていて、Bの変更が影響を与える場合。
    • 使用 (usage): 点線矢印。引数と戻り値に使わず、関数内で一時的に使うだけ。依存の特殊系。

Umbrello

Problem

altなどの重なり順番、アクティブの下になっちゃう

optの条件が表示されない。

Papyrus

Papyrus Dowloads

Papyrus Documentation

Tutorial

公式の[A slide-ware tutorial on Eclipse Papyrus usage for starters (2010-10-01)]を参考に基本的な使い方を学ぶ。

[File]-[New]-[Papyrus prooject]

これでプロジェクトを作ると、以下が [Project Explorer] に作られる。

  • <project name>
    • <project name>
      • di: ツールメタデータ。モデル作成のエントリーポイント。
      • notation: 画像データ。
      • uml: UMLモデルデータ。

このdiをダブルクリックして描画を開始する。

1個のプロジェクトでいろんな図に対応していて、モデルを流用できる形になっている。悪くない。これを使う。

画面構成

  1. Project explorer
  2. Model explorer: 一番重要。ここでモデル全体をツリーベースで管理する。
  3. Outline view: アウトライン
  4. Main toolber: ツールバー。
  5. Perspective: Model explorerの内容を使って作図する領域。
  6. Property view: モデルのエディター画面。

Model explorerがPapyrusの本質。ここでクラスとかインタラクションを定義しておいて、この定義をperspectiveの作図に使うイメージ。

クラス図やシーケンス図もModel explorerに所属していて、好きなだけ作れる。[New diagram]から作れる。

[New Child] でいくつか重要なモデルがある。

  • Package: ディレクトリ・フォルダーみたいなもの。これで他のモデルをまとめて整理できる。
  • Interaction: シーケンス図表現用のモデル。
  • Class: クラス。Interactionの型だったりする。UMLのベースで非常に重要。

Class

属性表示

クラス図にクラスモデルを配置しても、プロパティーやメソッドが表示されない。

右クリック-[Filters] で制御できる。

  • [Synchronized with Model] を選ぶと同期されて全部表示される。基本はこれで、一部だけ表示したい場合にここを外すのだろうと思う。
  • [Show/Hide Contents] で表示可否をチェックボックスで選べる。
Modelへのジャンプ

クラス図などからオブジェクトのModel Explorerの元データにジャンプしたいことがある。

オブジェクト右クリック-[Navigate]-[Go to ...]-[Model Explorer] を選ぶ。

Comment

https://chatgpt.com/c/67aec9f8-6be0-800b-b6eb-6300425ad1d4

メソッドなどにコメントを入れたいことがある。このコメントがわかりにくい。

[Properties]-[Comments]-[Owned comments]-[Body] に入力する。初回+で作ったダイアログのBodyに入力したものは反映されなくて、一度空のコメントを作った後に、洗濯後横のBodyに入力すると反映される模様。

  • Applied comments=他のモデルのコメントを取り込みたい場合に使う。
  • Owned comments=自分自身のコメント。コメントに対してコメントをつけることもできるので、[Create a new Comment] はさらに [Comments] タブを持っている。このタブがコメントのコメント。基本は使う必要ない。

[Annotated element] でたぶん、Bodyに入力したコメントを複数の要素に適用したい場合の適用先だと思う。

Sequence diagrams

https://eclipse.dev/papyrus/resources/PapyrusTutorial_OnSequenceDiagrams_v0.1_d2010100.pdf

2.2 Adding messages (basic - asynchronous)

コミュニケーションは、メッセージの交換で描写される。

メッセージはoperationCall (同期/非同期) かsignal (非同期) コミュニケーションとして表現される。

synchronousCall作成時は、replyMessageも期待される。

createMessageとdeleteMesageの指定は、ライフラインの動的な有無を意味する。

Papyrusでのメッセージ作成は以下の手順で構成される。

  1. パレットからツールを選択。
  2. ソースLifelineの開始点をクリック。
  3. ターゲットLifelineの終了点をクリック。
  4. ポップアップの該当するsignal/operationを選択。

記法

  • 非同期メッセージは中抜き矢尻 (arrow head)。
  • 同期メッセージは塗りつぶし矢尻。
  • 返信メッセージは波線 (dashed line)。
  • オブジェクト作成メッセージは波線+中抜き矢尻。
  • Lost Messageは黒丸矢尻。
  • Found Messageは黒丸矢柄。
2.2.1 Select desired tool from the palette
  • Message SyncとMessage Replyは [Execution Specifications] がないと使えない。
  • Message createはターゲットポイントが存在時に使用可能。
2.2.2 Select source and target points

ソースとターゲットポイントは2の異なるライフライン (通常) か、同じライフライン (再帰) が選択可能。

ターゲットポイントの制限は、対象の要素に依存する。例えば、Synchronous CallはExecution Specificationから始まる必要がある。

2.3 Adding execution specification

ここまでのシーケンス図では、通信シナリオだけを想定してきた。が、実際には、完全な実行トレースを表現できる。Execution Specification (ES) は実行を表す抽象概念で、Action Execution SpecificationとBehavior Execution Specificationの2種類がある。

PapyrusではライフラインにESをセットして行う。ESをセットしたら、同期メッセージを追加できる。

開発プロセスでは、予備設計では全メッセージを非同期とみなしておいて、設計時にESを設定して、同期メッセージをする感じ。

ただ、同期メッセージは、応答メッセージが入ってごちゃごちゃする。単にシーケンス図を書くだけなら、非同期で全部書いてもいいと思う。

Undoで破損

シーケンス図を作成して、削除のUndoを何回かやると、データが破損して開けなくなる。対応方法不明。GitでPapyrusのファイルを管理しておいて、破損に対応しておいた方がいい。

再帰自己呼び出しシーケンス図

シーケンス図の描画に癖があるので、方針を固めて使用する。

  1. 自己関数の呼び出しはMessage Async/Message Reply。Message Syncは期待通りに配置されないので、自己関数には使わない。他のライフラインには使う。
  2. 関数の呼び出し期間はAction Execution Specificationを配置。
  3. 矢印の端にESを配置する形にする。
オブジェクトの移動

オブジェクトの移動に癖がある。基本的に、メッセージは始点、終点で別々に移動させるしかない。まとめて選択して一括移動ができない。

終点を移動させると、その下のオブジェクトも追随する。追加はこれで対応できる。減らすのは手間になる。

シーケンス図が大きくなりすぎないように注意する。

Design

Atomic Design

最近のUIのコンポーネントの組み方。UIコンポーネントを粒度に分けて、ディレクトリー分けして流用するという考え方。

  • atoms: 原子。これ以上分割不能な最小単位。input/label/buttonなど。
  • molecules: 分子。atomsを組み合わせたり、atomsに多少修正したもの。入力フォーム、ナビゲーション、カードなど。
  • organisms: 有機体。分子+アルファ。入力フォーム+ヘッダーなど。複数の分子。
  • templates: テンプレート。複数の有機体。ヘッダー、メイン、フッターなど。
  • pages: ページ。テンプレートを使用したページ。

インターフェイスと抽象クラス

オブジェクト指向でよく登場するインターフェイス、抽象クラス、クラスの違い。

  • インターフェイスは、クラスに複数実装できるが、抽象クラスは1つしか継承できない。→不特定のクラスで、共通のメソッドを定義したい場合。
  • インターフェイスは、実装のあるメソッドを持つことができないが、抽象クラスは、実装のあるメソッドを持つことができる。→抽象クラスは、複数のクラスの、共通処理の中に、一部違う処理が入る場合、プロパティーが必要な場合などに使用する。

インターフェイス

  • メソッド宣言のみ。
  • static/constの場合に限定して、メソッド定義、定数もOK。
  • 多重継承可能。
  • tagのイメージ。

例えば、複数のクラスで共通の処理がある場合、その共通部分をInterfaceにして、それを継承すると良い。その部分だけ取り出して流用できる。

例えば、[Animal<-Duck] のような関係がある時、Duckは空も飛べるし、泳ぐこともできるとしたら、飛べることと泳げることの機能はAnimalの中でも対応がわかれる。こういうところをInterfaceにしておくと、振る舞いを統合できる。

抽象クラスは一部共通にしたい場合に使う。Interfaceは指定機能を全部共通。

ベースは抽象クラス、クラスにしておいて、複数クラスで共通にしたい場合interfaceで定義するときれいに実装できる。

Config class

アプリケーションの設定を管理するクラスの設計方法。いくつか方法があり、議論がある。「Best way to provide configuration parameters for objects far away from the starting point - Software Engineering Stack Exchange」で特によく議論されている。

  1. シングルトン/グローバル変数: ただし、テストなどで並列アクセスが必要な場合に困ることがあるらしい。
  2. DI/設定クラス引数: これがよく支持されている。テストしやすいなど。グローバル変数への参照を渡すようなイメージ。ただし、依存性の伝播のように、上から下に設定を渡す際に、関係ない大量の設定を渡すことがあったりする。

2のDIが最近の主流。引数で値渡し相当にすれば、並列アクセス時も無影響。伝播の問題は設計の問題。

メソッドをmain関数で呼び出すことを想定して、必要なものだけ渡るようにして、余計なものは削除する。上位・下位の関係を明確にすれば、渡すだけのパラメーターを排除できる。

do-while/if

複雑なif文と相性がいい。

for whileの無限ループで最後にbreakでも同じか

do {
  if (true) break;
} while(false);

if文が複雑な場合、do-whileで囲んで、breakでスキップできる。gotoに近い。

GoF

基本的に、具象クラスを使わずに、インターフェイスや抽象クラスを使ってインスタンスを生成するというのが、共通する基本パターン。

これにより、いろんなケースに同じコードで対応できる。

Factory Methodパターン

なぜあんなに難しい?Factory Methodパターン - ecbeing labs(イーシービーイング・ラボ)

コンストラクターの代わりに、インスタンスを生成 (工場=factory) となるメソッドを使うから、FactoryMethodパターン。

引数の内容に応じて、異なるクラスを作成する。

ただ、Factory Methodパターンを採用すると、コード量が増えて複雑になる。

複雑でややこしいだけなので、基本的に使わなくてよいと思う。

Naming

camelCase

https://gnusocial.jp/notice/7694551

!it 命名規則のキャメルケース。これ英語前提です。関数名に英語以外を使うと破綻します。

getキーバリュー()みたいな関数の定義。日本語ですると境界がわからなくなるので、getキー_バリューみたいにアンダーバーで区切ったほうが分かりやすい。なるほど…

getMyVariable() vs myVariable()

getterとsetterの命名規則。

getVar()にするか、Var()にするか。C++だと後者のパターンがあったりする。getを省略できるので、省スペースになる。

ただ、コード補完で探しやすさがちょっと変わる。getを前置したほうがわかりやすいか。

namePrefixed() vs prefixedName()

https://chatgpt.com/c/673bd358-3dc8-800b-8ec9-d745cc0eba85

名詞+修飾語 (形容詞) の場合のメソッドの命名規則。name+修飾語が複数ある場合name+修飾語がいい。オブジェクト指向でnameをオブジェクトとして扱う形に近い。name.methodみたいな。

例えば、nameMax、nameMinのような場合は後ろのほうが都合がいい。ただ、こういう場合はそもそもnameをオブジェクトにしてname.max()、name.min()にしたほうがいいという説がある。

そうではないならば、getPrefixedName()などが自然。getQueryString()など。StringQueryではない。

PHPでは以下のような命名規則が好まれる。

  • 動詞+修飾対象=getPrefixedName/isPrefixed()
  • 修飾対象+状態/修飾語=prefixdName

getPrefixedNameがいいか。後置修飾にしたいならば、そもそもオブジェクト+メソッドにすることを検討する。

map

連想配列とかハッシュ、オブジェクトなどでキーバリュー形式のデータ構造を扱うことがある。そういう変数の命名規則。

map_[key]_[value] のような形式にすると、キーとバリューが何を意味するか分かってわかりやすい。

https://chatgpt.com/c/67ca84e0-9018-800b-9674-035ae9f4bbaf

  • [key]_[value]_map
  • [key]_to_[value]

上記のどちらかがいいだろう。toがkey_valueの区切りが明示的でいいかもしれない。

array/foreach

foreach系のfor文ではキーとバリューを変数に格納して反復する。ファイルや配列に対して行うことが多い。

foreach (table as $row => $line)

その際の変数名は、上記のように$row/$lineにすると、行番号と行の値がはっきりしてわかりやすい。

いいえ。これは問題がある。ネストした場合などに命名規則を維持できない。

  • 配列、コレクション類: 複数形があるなら複数形。困ったらListの接尾辞。
  • 反復時。キーバリュー形式の場合、単数形_key/_value。valueだけの場合、単数形。また、_valueは単数形でもいいかもしれない。

上記の命名規則だとわかりやすい。

$rows = [[]];
foreach ($rows as $row_key => $row_value) {
  foreach ($row_value as $column_key => $column_value) {}
}


foreach ($row_list as $row_key => $row) {
   foreach ($row as $column_key => $column) {
   }
}


foreach ($rows as $row_index => $row_value) {
  foreach ($row_value as $column_index => $column_value) {
  }
}

value部分に単数形を使うと、検索時にkey部分もヒットして、作業しにくいかもしれない。基本はkey/valueの接尾辞がよいと感じる。

もっというなら、接尾辞の文字数が揃うので、keyよりindexのほうがよいかもしれない。ただ、indexは添え字の数字の意味合いが強いので、やっぱりkey/valueでいいか。

Function argument order

関数の引数は入力、変更、出力の順番にする。理由はこの順番で使うから。

https://social.senooken.jp/notice/67270

うーん。今晩は,CODE COMPLETEでC言語の関数の引数の順番を調べたりしていて,勉強時間がないな…

int func(入力,変更,出力)

この順番。理由は,この順番で使うから。

memcpyとかは例外が多い。

x = bの語順からきているからとの憶測がある。

https://okwave.jp/qa/q4202225.html

get/fetch

https://chatgpt.com/c/67bd1a05-d3a0-800b-88d8-f4f47b995560

  • fetch=外部から取得する意味。DBや外部Web APIから取得する場合にfetchがいい。
  • get=手元から取得する意味。プロパティーなど内部から取得する場合。
list/data

fetchList/fetchDataのどちらがいいか?

  • list=配列。必ず配列。
  • data=全部。配列以外にnullや単一データがあるならこちら。

基本はfetchListでいいと思う。

Order

https://chatgpt.com/c/67ca7edf-f92c-800b-8174-9706bfba3ff3

関数実行の順番が大事なときと、そうでないときがある。区別し難い。

順序を明示したい場合、メソッドチェーンを使うのが確実。

他に、前の関数の結果、戻り値を後続の引数に渡すなら、それも悪くない。

privateの先頭_

privateなメソッド、プロパティーで、先頭に_をつけることがある。

https://chatgpt.com/c/67da92b1-1650-800b-b347-f16f76fd549a

privateのアクセス権、可視性の機能があるなら、それを使えばいいので、_は不要。むしろないほうがいいらしい。PHPのPSR-12では禁止されている。

PSR-12: Extended Coding Style - PHP-FIG

Property names MUST NOT be prefixed with a single underscore to indicate protected or private visibility. That is, an underscore prefix explicitly has no meaning.

Pythonのように、言語的にないなら、やむを得ない。

PHPは昔privateがなかったので、そういう古いコードとの一貫性の維持が目的なら、先頭_もあり。

配列の要素数

https://chatgpt.com/c/67ecd6ff-b06c-800b-8f44-cfeb9c5768bb

配列の要素数、長さを変数に格納して使うことがけっこうある。その際の変数名。

オブジェクト指向に従うなら、配列名_size/countの接尾辞がいい。

C++のvectorなどのコンテナーだと.size()でとれる。変数に格納せずにsizeでいい。

変数にあえて代入するならば、配列名_sizeが自然。

ただ、PHPだと、countで要素数を取得する。その都合で、_countがよい。

item_list = [];
item_list_size
item_list_count

OOP

継承とtrait

https://chatgpt.com/c/67cea053-9f50-800b-b22f-67aea7ac0dfe

apcとstaticのキャッシュクラスがあって、それとは別にビジネスロジックの共通化をしたい場合、いくつか方法がある。

  1. apc と static を統合した親クラスで trait を use し、子クラスで継承する
  2. apc と static を子クラスで直接継承し、trait を use
  3. 継承(extends)ではなく、キャッシュクラスを別のクラスとして利用する という考え方です。
依存注入(DI)・継承・trait の使い分けまとめ

https://chatgpt.com/c/67cea053-9f50-800b-b22f-67aea7ac0dfe

キャッシュやORMのような、切り替え可能な機能の場合、DIで実装してプロパティーに格納して使うのが使いやすい。DIはテストのしやすさに勝る。

継承は親子関係が明確な場合。

コンストラクターのアクセス権

基本はpublicだが、privateとprotectedを指定する場面がある。デザインパターンと関係している。

https://chatgpt.com/c/67fdac9a-2fac-800b-91bf-460c10fd72f5

  • protected: 継承先のみ。ベースクラスや抽象クラスで使用する。ベースクラスや抽象クラスは継承を前提とするから、直接インスタンス生成してほしくないから。ファクトリーパターンと組み合わせる。
  • private: クラス内部のみ。シングルトン・ユーティリティー (静的ファクトリーメソッド専用クラス) 系クラスで、インスタンスを作って欲しくない、1個だけのように、インスタンスの生成数を制限したい場合。

DB

PDOの真の力を開放する - PHPでデータベースを扱う(3): Architect Note

DBアクセスのモデル化。行をクラスとすると扱いやすい模様。

getterを作ったり、データの妥当性のチェックなどもできる。

select/insert/などはmapperでクラスとDB列名を対応付けて処理する。自前で実装する場合はこういうつくりがいいらしい。

データベース関係のデザインパターンがいくつかある。

  • Active Record
  • Data Mapper
Active Record pattern

テーブルレコードに対応するクラスを用意して、そのクラス自体にDB操作もさせる。

シンプルだが、複雑な操作が苦手。

エンティティーがテーブルと密接なため、例えばテーブル構造が変わった場合に大量に修正必要。

Ruby on Rails/Laravel+Eloquentなどで採用。

Data Mapper pattern

第14回 DataMapperの使い方 | gihyo.jp

テーブルのレコードをクラスにするのはARと共通。

ただし、DB操作用のクラスを用意してそちらでDB操作する。

その都合、1テーブルに2クラス必要。

User/UserMapperのような対応関係。

2クラス必要だが、テーブル構造が変わった場合でも基本はMapperで吸収できる。

JOIN

Active RecordもData MapperもJOIN時の扱いが一番重要。単一エンティティーしか扱わないならどちらも同じ。

基本はエンティティーのプロパティーに持たせる感じ。

datamapperパターンでjoinする場合、エンティティーの扱いはどうなるの?

`DataMapper`パターンで`JOIN`を行う場合、エンティティの扱いは設計次第ですが、いくつかの注意点があります。`DataMapper`パターンは、データベースのテーブルとエンティティの間にマッピングを行い、エンティティはドメインロジックを持ち、データベースアクセスの責務を持たないことが特徴です。そのため、`JOIN`の処理をどの層で行うかを慎重に設計する必要があります。

以下、`JOIN`を行う際のエンティティの扱いと実装方法について解説します。

      1. 1. マッパークラスでの`JOIN`実装

`JOIN`を伴う複雑なクエリが必要な場合、マッパーが直接`JOIN`を使って複数テーブルを組み合わせた結果を取得し、それを複数のエンティティとしてマッピングする方法があります。例えば、ユーザーと注文を持つシステムで、ユーザーとその注文を一緒に取得したい場合、`UserMapper`で`JOIN`を行い、結果セットを`User`と`Order`エンティティに分割してマッピングします。

```python

class UserMapper:

    def find_user_with_orders(self, user_id):

        sql = """

            SELECT * FROM users

            JOIN orders ON users.id = orders.user_id

            WHERE users.id = %s

        """

        results = self.db.execute(sql, (user_id,))

       

        user = User(results[0]['user_id'], results[0]['user_name'])

        orders = [Order(row['order_id'], row['product_name'], user) for row in results]

        user.orders = orders

        return user

```

この方法では、1つのSQLクエリで必要なデータをすべて取得し、エンティティのプロパティにそれぞれのデータを設定します。

      1. 2. リポジトリでの集約

`JOIN`を使わず、各エンティティを個別に取得した後、リポジトリが集約の役割を担う方法もあります。リポジトリが各エンティティの`Mapper`を呼び出し、必要なエンティティ同士を関連付けることで`JOIN`を再現します。例えば、まず`UserMapper`でユーザー情報を取得し、次に`OrderMapper`で該当ユーザーの注文を取得してエンティティ間で関連付けます。

```python

class UserRepository:

    def __init__(self, user_mapper, order_mapper):

        self.user_mapper = user_mapper

        self.order_mapper = order_mapper

    def get_user_with_orders(self, user_id):

        user = self.user_mapper.find(user_id)

        orders = self.order_mapper.find_by_user_id(user_id)

        user.orders = orders

        return user

```

UserテーブルとOrderテーブルがあって、あるユーザーの注文一覧を取得したい場合を考える。

結局、user.ordersみたいな感じで、エンティティーに外部テーブルのレコードを配列で持たせるつくりになる。

クロス集計する場合は、users[0].orderみたいな感じ。メインのエンティティーのプロパティーに持たせる。フラットじゃないのでちょっと気持ち悪い。が、まあ構造としてこうなるのは順当。

方法として、1回のSQLで取得するか、それぞれのエンティティーを取得してマージするか。1回のSQLでやったほうが当然いい。

Other

1対1-多対多

プログラミング言語でデータの関連付けをすることがある。

1対1の場合、配列、連想配列のキーバリュー形式のデータがぴったり。

多対多の場合。これも配列。二次元配列で基本は0要素目など。

$array[][]

Project

レガシープロジェクトの立て直し

https://chatgpt.com/c/67481a93-adc0-800b-81c4-20d763133002

1. 現状分析

(1) ソフトウェアの動作確認

現在の環境でアプリケーションを動作させる。

どの部分が機能していて、どこが問題かを確認する。

必要であればエラーログを確認する。

(2) 依存関係の調査

アプリケーションのライブラリやフレームワークのバージョンを調査。

サポートが終了しているもの、互換性が失われたものを特定。

(3) コードベースの状態評価

コードの品質 (可読性、設計、テストカバレッジ) を確認。

セキュリティリスクを特定する (例えば、脆弱性が放置されていないか)。

2. 計画立案

(1) ゴール設定

具体的な目標を設定 (例: パフォーマンス改善、保守性向上、セキュリティ強化)。

(2) 優先順位の決定

どの機能を維持し、どの機能を削除または置き換えるか決定。

ユーザーに直接影響を与える部分を優先。

(3) リスク評価とバックアップ

修正に伴うリスクを評価し、現行システムのバックアップを取得。

3. 環境整備

(1) 開発環境のモダナイズ

ローカル環境やコンテナ (Docker) を用意してテストを容易にする。

CI/CD パイプラインの整備。

(2) 依存関係の更新

サポートされていないライブラリやフレームワークをアップグレードまたは置き換える。

(3) セキュリティの確保

古いOSSの脆弱性を修正。

HTTPSの導入、認証強化、インプット検証など。

4. コードのモダナイズ

(1) リファクタリング

レガシーコードをよりモダンで可読性の高いコードに変換。

デザインパターンを適用して保守性を向上。

(2) テストの追加

ユニットテスト、統合テストを導入。

既存の機能が壊れないことを確認するための自動化されたテスト。

(3) フロントエンド/バックエンドの分離

必要に応じてモノリシック構造を分離し、モダンなアーキテクチャ (SPA、Microservices など) に移行。

5. 機能拡張とデプロイ

(1) 新しい機能の追加

必要に応じて、現代のニーズに合った新機能を実装。

(2) 運用環境でのテスト

新しい環境で徹底的にテストし、問題がないことを確認。

(3) 本番環境にデプロイ

ロールバック計画を準備しつつ、安全にデプロイ。

6. 継続的改善

(1) モニタリングの導入

エラーログやパフォーマンスを監視し、迅速に対応できる仕組みを導入。

(2) 定期的なアップデート

フレームワークやライブラリを継続的に更新し、レガシー化を防ぐ。

(3) コミュニティへの貢献

OSSとしての性質を活かし、変更内容をコミュニティに共有することでフィードバックを得る。

このプロセスを通じて、安定した動作を保ちながら徐々に近代化することが可能です。特に、「現状分析」と「環境整備」をしっかり行うことで、後続の作業がスムーズになります。

AI

対話AI

List

【2024年版】対話型AIサービスおすすめ11選を徹底比較!チャットボットとの違い・メリット・課題・選び方なども紹介 - NotePM

いろいろある。

Name
Bing
Perplexity AI
ChatGPT
Google Gemini

ChatGPT

Plan

ChatGPT | OpenAI

Free/Plusの2のプランがある。

Free Plus
金額 [USD/月] 0 20
機能 基本 アーリーアクセス
エンジン GPT-4o mini GPT-4/GPT-4o/GPT-4o mini
制限 - GPT-4oの5倍以上のメッセージ送信
その他 - データ分析、ファイルアップロード、ビジョン、Webブラウジング
画像生成 - DALL-E

送信可能なメッセージ数、エンジン、画像生成などが大きな違いだろう。

Account

公式サイトにアカウントの意味の説明がない。しかたないので、ChatGPTに質問。

ChatGPTに会員登録する意味は何ですか?


ChatGPTに会員登録する主な利点はいくつかあります。

1. **パーソナライズされた体験**: 登録すると、あなたの好みや過去のやり取りに基づいて、よりカスタマイズされた応答が得られます。

2. **履歴の管理**: 過去のチャット履歴を保存し、いつでも見返すことができるため、情報の確認が簡単になります。

3. **新機能へのアクセス**: 登録ユーザーは新しい機能やアップデートを優先的に利用できる場合があります。

4. **プレミアム機能**: 一部のサービスでは、会員登録をすることで、より高度な機能やサポートが提供されることがあります。

5. **セキュリティとプライバシー**: アカウントを持つことで、データの管理やプライバシーの設定をより細かく調整できます。

興味があれば、ぜひ登録を検討してみてください!他に質問があればお知らせください。

自分の過去の質問の履歴を見れるだけでも便利かも。

方法
質問の分割

https://chatgpt.com/c/673bdc0d-e0e0-800b-a22b-4fa19e64476c

Q. chatgptで質問するとき、連続して質問すると、同じURLで複数の質問が表示される。リロードして質問を分けたほうがいいのか?

A. どちらでも問題ない。が、質問が関連しているなら同じチャットで継続したほうがいい。直前の質問も文脈を考慮できる。完全に話が異なるなら分けたほうが後で整理したり、URLを共有したときにわかりやすい。

感想
2024-11-14 Thu

https://gnusocial.jp/notice/7806505

!it !ai 業務でPHPの開発作業をしていて、ChatGPTを使いだして便利に感じています。検索エンジンの代わりに使っています。

例えば、「laravel eloquentでリレーション先のテーブルの主キー名の取得方法は?」と質問します。

https://chatgpt.com/c/67354314-fbdc-800b-a4e4-65f96d1a8fb2

getRelatedというややマニアックなメソッドを教えてくれます[eloquent getrelated] で検索してもなかなかたどり着けないです。

こういう検索エンジンで検索しにくい質問で便利だなと思います。

検索エンジンで検索すると、的外れな情報も大量にヒットします。対話AIはそのごみの混ざった検索結果を分析した結果をコンパクトに返してくれます。対話AI使わなくても、検索エンジンで時間かければわかりますが、大幅に時間短縮できます。

大量の凡人健常者が取り組んだ方法論として決まりきったものは、記憶の問題、ただの神経衰弱です。こういうのを検索エンジンの改良版としてAIに任せるのはいい使い方だと思います。

個人的に、ただの知識、事実は重要度高くないと思いますが、一般社会では評価する側の頭が悪いので、これが重宝されます。

同僚や先輩に聞くより対話AIのほうがよほど頭いいです。話すことないです。聞くほうが時間の無駄なので。凡人はどんどん要らなくなります。

一方、私みたいなキチガイのデータは少ないので、検索エンジンやAIに聞いても出てこないです。世界で自分だけのオリジナルに専念するのがたぶんいいです。

2024-11-19 Tue

https://gnusocial.jp/notice/7867350

!ai ChatGPTが検索エンジンの改良版としてやっぱり便利。さっきこういう質問しました。

phpのメソッド名で、英単語の修飾語は前と後ろどちらがいい?例えば、namePrefixed()とprefixedName()のどちらがいい? https://chatgpt.com/c/673bd358-3dc8-800b-8ec9-d745cc0eba85

私はこのレベルの細かい疑問がすぐ浮かぶのです。これを人間にきくと、頓珍漢な回答だったり、そもそも回答してもらえないし、何ならこういう質問した私がなぜかキチガイ扱いされて、微妙な雰囲気になって、質問できなくなって、ストレスが溜まって、居づらくなって早期退職になるんです。意味不明です。ただの質問にお気持ちの配慮とか面倒なので。

この間、 @yuriha に突っ込まれた件も、たぶん対話AIとお互い会話したほうが有意義だったんじゃないかとすら思います。相手も私に突っ込む前に対話AIと会話したほうが自分の主張の自己矛盾、頓珍漢さに気づけたんじゃないかとすら思えます。私が突っ込んでまーた私がキチガイ扱いされるのも回避されます。対話AIからの客観的な指摘なら、同じ内容であっても、キチガイの私が言うより納得しやすいでしょう?同じ内容なら対話AIのほうが凡人健常者にとっては、信じ込みやすいでしょ?

対話AIだとお気持ちの配慮いらないし、当たり前ですけど、キチガイ扱いされることもないので、快適です。元々対話AIには懐疑的でしたが、どちらかというと私のようなキチガイが凡人健常者の知識を拝借するためにあるような印象を持ちます。

検索エンジンでも調べることはできますが、めちゃくちゃ時間かかるんです。自分で複数の意見をみつけて、頭の中で比較検討して整理するので。これを一瞬でやってくれるのが楽。途中のデータ整理、目視は単純作業に近いのです。他のことに頭使えます。

もはや技術とか、ただの暗記の神経衰弱は別にいらないです。一般企業の上長とか、士業のように、単純知識でマウント取るタイプの仕事はこれで確かに駆逐されます。どうせ対話AIのほうが賢いのだから。知識量で勝てるわけないです。全世界の情報の集積結果なんだから。

凡人健常者の知識を拝借して、世界でだれにも真似できないキチガイ部分に専念できます。GNU socialの開発もこれでいけると思います。

Shell

Shell Command Language

Compound Commands

Shell Command Language

Case Conditional Construct
case word in
    [(]pattern1) compound-list;;
    [[(]pattern[ | pattern] ... ) compound-list;;] ...
    [[(]pattern[ | pattern] ... ) compound-list]
esac
  • 未マッチで終了ステータス0。
  • pattern部分: シェル展開が有効。他はglob。
  • |でOR検索相当。
  • 最後のパターンの;;は省略可能。if文のようにも使える。
  • 全パターンの捕捉は最後に*。空でもマッチする。?は最低1文字必要。

BREでは未対応な|のORマッチに対応しているのが最大の特徴。文法なのでコマンドを実行せず早い。grepを使わずにできるだけこちらを使ったほうがいい。

ワイルドカード

ワイルドカードで.始まりのファイルをマッチさせたい。

以下ならマッチするが、ブレース展開 (brace expansion) はPOSIX shでは使えなかった気がする。

echo {.*,*}

BOM

unicode - Adding BOM to UTF-8 files - Stack Overflow

ExcelでUTF-8ファイルを開けるように、UTF-8のBOMをファイルにつけたい。

printf '\xEF\xBB\xBF' > with_bom.txt

上記コードでBOMを最初に書き込んで、後は追記する。

awk

The Open Group Base Specifications Issue 7

変数

特別
  • NF: 列数。列の全表示などで使う基本的で重要な変数。
  • NR: 行番号。
スコープ

変数のスコープ

関数の仮引数のみ、ローカル変数扱いで、それ以外はグローバル変数。

文/statement

  • actions
    • if/else
    • while/do...while/for
    • break/continue
    • delete
    • next
    • exit
  • output
    • print
    • printf

関数

組込関数
  • Arithmetic
    • atan2
    • cos
    • sin
    • exp
    • log
    • sqrt
    • int
    • rand
    • srand
  • String
    • gsub
    • index
    • length
    • match
    • split
    • sprintf
    • sub
    • substr
    • tolower
    • toupper
  • I/O
    • close
    • getline
    • system

print/printfは関数ではなく、statement/文扱い。

ヘッダー出力、列別最大長さ出力。

awk -F, '{if(NR==1) print $0} {for(i=1; i<=NF; ++i){if (line[i] < length($i)) line[i] = length($i)}} END {for (i=1; i<=NF; ++i) {printf line[i]","}}' data/101542.csv

CSV

シェルスクリプトの実験のために作った POSIX 準拠 awk 実装の CSVパーサー (RFC4180対応) #ShellScript - Qiita

# csvparser.awk

## Usage
# awk -f csvparser.awk data.csv

# CSV の論理的な一行毎に呼び出されるコールバック関数(サンプル)
# row: 行番号(最初の行は1) len: フィールド数 fields: フィールドデータ
function callback(row, len, fields,  col, field) {
    for ( col = 1; col <= len; col++ ) {
        field = fields[col]
        gsub(/\\/, "&&", field)  # \ は \\ にエスケープする
        gsub(/\n/, "\\n", field) # 改行は \n にエスケープする
        print row ":" col " " field
    }
}

BEGIN { row = max_idx = 0 }
{
    idx = 0
    sub(/\r$/, "")
    while ($0 != "") {
        if (match($0, /^(["]([^"]|["]["])*["]|[^,"]*)(,|$)/)) {
            fields[++idx] = ""
        } else if (match($0, /^["]/)) {
            fields[++idx] = substr($0, 2)
            for (;;) {
                if (getline == 0) exit 1
                sub(/\r$/, "")
                if (match($0, /^([^"]|["]["])*["](,|$)/)) break
                gsub(/["]["]/, "\"")
                fields[idx] = fields[idx] "\n" $0
            }
            fields[idx] = fields[idx] "\n"
        } else {
            exit 1
        }
        field = substr($0, RSTART, RLENGTH)
        $0 = substr($0, RSTART + RLENGTH)
        lastcomma = sub(/,$/, "", field) > 0
        gsub(/^["]|["]$/, "", field) && gsub(/["]["]/, "\"", field)
        fields[idx] = fields[idx] field
    }
    if (lastcomma) fields[++idx] = ""
    while (idx < max_idx) delete fields[max_idx--]
    callback(++row, idx, fields)
    max_idx = idx
}

awkのCSVパーサー。先頭のBOMはあると認識できないので、tail -c +4でBOMを除外して使う。

tail -c +4 data/101543.csv | awk -f csvparser.awk 

Other

binary

POSIX準拠のシェルスクリプトでバイナリデータを扱う #Bash - Qiita

バイナリーデータの読込はodコマンド。なければhexdump。

書込はprintf。

head/tailの-cはPOSIXで使えたか?

root

リダイレクト出力

sudo権限でリダイレクト処理を行ってファイルに書き込む方法

リダイレクトはログインユーザーの権限でなされるらしく、root権限のある場所にファイル出力できない。

teeコマンドでやる。

pwd | sudo tee out.dat

teeコマンド実行する側でsudoが必要。


ログインシェルの確認

第 10 章 動作環境のカスタマイズ (Solaris ユーザ ログインシェルはGUIログインでも内部的にある。ログインシェルが読みこむprofileファイルなどは、ログイン時に、1回だけ実行したい処理の記述場所として最適。 SHELL環境変数にログインシェルのパスが入っている。

echo $SHELL
/bin/bash

OSの判別

OSTYPE環境変数に値があるのでこれで判別する。 例えば以下の値が入っている。

linux-gnu
darwin23

これらを検知して判定する。

case $OSTYPE in
  linux*) echo 'linux';;
  darwin*) echo 'Mac';;
esac

Configure

profile

bash の初期化ファイル .profile, .bashrc, .bash_profile の使い分けと管理方針 - A Memorandum 環境変数など~/.profileに全部のシェルの共通設定を記述して、~/.bash_profileなどのログインシェルやbashrcなどで参照するのがいい。

cmd.exe

Control block

for

あくまでコマンド。

nest

ネストはできない。二重ループしたければ、関数にしてそれを呼び出す。

bitsadmin

Windowsでのファイルダウンロードコマンド

Windows 7以降ではbitsadminコマンドがあり、これがwget相当となる。

書式:

bitsadmin /transfer <job name> <URL> <output path>

<job name>と<output path>は必須なので注意する。

certutil

Windowsでのハッシュの確認に使える。

certutil -hashfile file
SHA1 ハッシュ (対象 C:\moconavi\windows\Moconavi\ext\chromium\moconavium.exe):
e0da85b04b6970ac1f0c33db7a9ad607fdbd44eb
CertUtil: -hashfile コマンドは正常に完了しました。

rlogin.cmd

コマンドキーの送信を自動化できる?

rem rlogin.cmd

@Echo off
Set SERVER=192.168.0.0
Set USERNAME=
Set PASSWORD=

Cmdkey /generic:TERMSRV/%SERVER% /user:%USERNAME% /pass:%PASSWORD%
Start mstsc /v:%SERVER%
Timeout 5
Cmdkey /delete:TERMSRV/%SERVER%

実行中プロセスのパスの確認

出典: Show EXE file path of running processes on the command-line in Windows - Super User

wmic process get ProcessID,ExecutablePath
wmic process where "name='mysqld.exe'" get ProcessID, ExecutablePath
wmic process where "name='mysqld.exe'" get ProcessID, ExecutablePath /FORMAT:LIST

簡易編集モード/挿入モード

Windows 10のcmd.exeは [簡易編集モード] が有効になっており、コマンドプロンプトを左クリックすると、テキストの選択が始まる。テキスト選択中はコマンドの実行が止まる。長時間かかるコマンドの実行中に誤操作で止まると困るので、これは無効にしたほうがよい。

cmd.exeを起動-左上のアイコンをクリック-[規定値]/[プロパティ]-[オプション]-[□簡易編集モード] を選ぶ。

そのほか、 git log のような制御が移るコマンドを実行してしばらくすると、操作できなくなる。

[□挿入モード] にすると回避できる模様。

Web

URL

クエリー配列

やり方がいくつかある。

  1. CSV文字列で受取後分割: https://www.sakdor.net/test/?var=1,2,3 explode(",",$_GET[var]);
  2. 配列添字
    1. http://www.sakdor.net/test/?var%5B%5D=1&var%5B%5D=2&var%5B%5D=3
    2. http://www.sakdor.net/test/?var%5Ba%5D=1&var%5Bb%5D=2&var%5Bc%5D=3
    3. http:www.sakdor.net?var[0]=1&var[1]=2&var[2]=3

データが決まっているならcsvがシンプル。

CGI

https://chatgpt.com/c/67634332-a3b8-800b-87a2-e21bd21a1cfc

WordPressなどのWebアプリだとファイル拡張子が登場しない。これはいくつかの仕組みが組み合わさって実現されている。

  1. パーマリンク設定 によるクリーンなURL構造の生成。
  2. .htaccess(Apache)リライトルール によるURLの書き換えとルーティング。
  3. index.php を起点とする動的な処理。
  4. テンプレート階層 に従って適切なPHPファイルを呼び出す。

.htaccessでindex.phpにリダイレクトして、index.phpから全て処理している。これにより省略できている。

同じ用に、アプリ側が対応していれば、index.fcgiに全部リダイレクトして、パスを解釈してくれるなら、/でのアクセスもできる気がする。

apache - How can I run a FastCGI script in root url (/ - without path)? - Stack Overflow

HTTP

RFC 9110: HTTP Semantics

Content-Disposition

Content-Disposition - HTTP | MDN

RFC 6266 - Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP)

Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="filename.jpg"

filenameでファイル名を指定する。ここの値は二重引用符で囲む。スペースを含む場合に必須になる。

multipart/form-data

rfc7578

ファイルアップロード用のMIME type。

リクエストヘッダー

Content-Type: multipart/form-data; boundary=--hogehoge

リクエストボディー

--hogehoge
Content-Disposition: form-data; name="user_name"
Content-Type: text/plain

test
--hogehoge
Content-Disposition: form-data; name="email"

sample@mail.com
--hogehoge
Content-Disposition: form-data; name="gender"

male
--hogehoge
Content-Disposition: form-data; name="user_profile" filename="image.jpeg"
Content-Type: image/jpeg

\xff\xd8\....
--hogehoge--

ヘッダーでmultipart/form-dataを明記して、ボディーでデータを指定する。

curlコマンドでPOSTする, 様々な形式別メモ |

curlでの送信理由。

-Fで送信データをname=data形式で指定する。ファイルの内容を指定する場合、@filenameで指定する。これを指定すると、リクエストボディーのfilename扱いにしてくれる模様。-Fを指定すると、-H 'Content-Type: multipart/form-data'が自動付与される。たぶん、-dと同様に-X POSTもつく。

curl -X POST -F file1=@/var/tmp/sample.jpg https://xxxxx.net/xxxxxx

データとテキストを同時送信したい場合、-Fで複数指定する。

curl -X POST -F 'age=30' -F file1=@/var/tmp/sample.jpg https://xxxxx.net/xxxxxx

curlだと上記のboundaryなどをうまくやってくれるのだと思う。

リクエストボディー全体をファイルデータにする場合。

curl -X POST -H 'Content-Type: image/jpeg' --data-binary @/var/tmp/sample.jpg https://xxxxx.net/xxxxxx

IP address

出典: 固定IPアドレスの取得方法 ~実は簡単!フリーランスの方も必見です~|VPN活用日記|トピックス|グローカルネットの快適VPN【公式】| 株式会社グローカルネット

自宅サーバーを行う際、固定IPアドレスが必要になる。

取得方法がいくつかある。

  • 契約しているプロバイダでオプションとして申し込む方法
  • 固定IPアドレスに対応しているSIMを契約する方法
  • VPNを利用した固定IPアドレスの提供会社を利用する方法

VPNの固定IPアドレスが安いらしい。ryoかsuwakoが解説していた気がする。

Authentication

認証方式がいくつかある。HTTPで定義される認証方式 (HTTP認証) が有名。

Basic認証

出典: Basic認証 - Wikipedia

Authorization HTTPヘッダーにBasicのあとに [username:password] をBASE64でエンコードして送信する認証方式。

GET /private/index.html HTTP/1.1
Host: example.com
Authorization: Basic cm9vdDpwYXNzd29yZA==

盗聴や改ざんが簡単だが、シンプルという利点がある。

Basic認証のキャッシュを削除する(ログアウトする) | DevelopersIO

ログアウト時は、hoge@domainのようにパスワードを省略した任意のユーザー名でログインを試みて既存のログイン状況を上書きする模様。

Digest認証も共通。

Digest認証

Basic認証・Digest認証・Form認証をざっくり理解 #Security - Qiita

HTTP標準の認証。Basic認証とほぼ同じ。ただし、パスワードをハッシュ化している。そのため、DBのパスワードが流出した場合に比較的安全。

OAuth

Ref

OAuth (オーオース) 権限の認可のための標準。OAuth 2.0が最新の標準。

以下が登場人物。

  • resource owner: あるサイトのユーザー。
  • resource server: あるサイトのユーザーのデータの保有サーバー。
  • clent: クライアントアプリ。リソースサーバーのデータを使用したい。
  • authorization server: クライアントにサイトへのアクセスを認証するサーバー。アクセストークンを発行して行う。

アクセストークンが実質的なパスワードのようなものだが、resource serverのパスワードを直接渡していない点が重要な違い。パスワードを直接渡さないことで、機能別に権限を細かく利用可否を制御できる。

処理の流れ。

  1. client->resource owner: Authorization Request。ここでユーザーが手操作でアクセスを承認する。
  2. client<-resource owner: Authorization Grant。
  3. client->authorization server: Authorization Grant。承認された情報でアクセストークンを要求。
  4. client<-authorization server: Access Token
  5. client->resource server: Access Token。アクセストークンでアクセス。
  6. client<-resource server: Access Token

Consumer Key/Secret: アプリ識別用のID/PW。

Access Token: サイトにアクセスするためのパスワード。

API

複数レコードの登録

複数レコードの登録・更新・削除のREST APIについて調べてみた話(+@ Graph API) - junode | 個人開発ブログ

既存のAPIは単一リソースの処理しかないことが多い。JavaScriptなどで単一リソースを何回も呼べばいいというのはそうだけど、JavaScriptなしでは動作しない。一括処理用のAPIを作るしかなくないか?

REST WebAPIのプラクティス | yamarkz.com

delete_bulkなどのような一括処理用のAPIを作るしかない。内部的には単一処理のAPIを作る感じだったとしても。

パラメーター

json - REST API Best practices: args in query string vs in request body - Stack Overflow

パラメーターの指定に3種類ある。

  1. リクエストボディー
  2. クエリー
  3. パス

パスはIDなどを指定する場合だけわかりやすい。それ以外のオプションはクエリーのほうがいい。

ボディーは、通常サーバーのアップロード・ダウンロードデータとして使われる。クエリーはデータの指定に使う。

この原則に従うとシンプルだろう。

  • URIには長さの制限がある。
  • ボディー
    • 引数が非常に多い場合。
    • 画像などバイナリーデータ。
    • キー・値構造を持たない場合。
  • クエリー文字列
    • 引数を簡単に確認できる。
    • 共通の引数の場合。

検索機能のGET/POST

検索機能にGETとPOSTのどちらを使うか?という議論がある。

データ登録するわけなじゃないのだから、GETがいいんじゃない?

POSTだと、JSONをそのまま送れるので、複雑なケースに対応できる。特に、配列の送信が重要。

GETのほうが検索条件をブックマークにできたり、URLを共有できるので、基本は便利。

ただし、検索などのパラメーターが長くなる場合、使用できない。そもそも検索でそんなに長いパラメーターというのがまずいかもしれない。2000文字あれば十分という説がある。

レート制限対策

いろいろ方法がある。

  • cronなどでデータをサーバー上 (DBなど) に定期保存して、保存データを表示させる。
  • 配列を利用して、1回のリクエストでまとめて取得する。
  • インターバルを設ける。
  • HTTP 429/413を検知して、リトライする。

指数関数的バックオフ

wait_interval = base * 2^n +/- jitter
  • wait_interval は、API が HTTP 429 で応答した場合に、システムがリクエストを再試行するまでの時間となります。
  • base は最初の間隔、つまり最初の再試行までの待ち時間です。この値には3000msを使用することをお勧めします。
  • n は、現在の呼び出しの前にリクエストが通らなかった数です。複数のスレッドやプロセスを使用して並行してAPIを呼び出している場合、nの値は現在のスレッド/プロセスにスコープされます。この値は、現在のスレッド/プロセスが、最後に成功した応答から何回 429 "Too Many Requests" エラーに遭遇したかを表します。
  • jitter は 0 から base の間の乱数です。これは、複数のスレッド/プロセスが全く同時にAPIを呼び出さないように、リクエストを少しずつ分散させるために使用されます。システムが待機するたびに、この乱数値を再計算し wait_interval の合計に加算するか減算するか、ランダムで選択してください。

バックエンドとフロントエンドの分離

https://chatgpt.com/c/6747e923-6174-800b-8816-dd741721de45

SPA (Single Page Application) やJAMStackの影響で、バックエンドはデータを返すだけで、画面描画はフロントエンドが全部するというのが最近の流行。

SSR (Server Side Rendering) とCSR (Client Side Rendering) の違い。フロントエンドの高度化や分業などが理由とのこと。

SSRの利点。

  • SEO
  • 初期表示。
  • 匿名。

SSRの課題。

  • サーバー負荷: データとHTML作成を同時に行うから。
  • 分散困難:

キャッシュの活用がポイントになるとのこと。

Network

ssh

ssh-addの自動登録

ssh agentに秘密鍵の登録は以下のコマンド。

ssh-add <秘密鍵のpath>

ただし、上記コマンドは再起動すると登録が消えるので毎回必要。

~/.ssh/configに以下の内容を記入しておくと、次回からkeychainから自動で読み込まれるらしい (macOS で再起動しても ssh agent に秘密鍵を保持させ続ける二つの方法 #SSH - Qiita)。

Host *
  UseKeychain yes
  AddKeysToAgent yes

うまくいかなかった。

ssh-addをPC起動する度に自動的に実行させるための設定 | AIFAN

id_rsaの場合はIdentityFileを省略できるが、それ以外は指定が必要な模様。

Host *
  UseKeychain yes
  AddKeysToAgent yes
  IdentityFile ~/.ssh/id_ed25519
ssh経由でのリダイレクト出力

bash - How to remotely write to a file using SSH - Super User

ssh経由で標準入力内容からファイルをリダイレクトで作成したいことがある。

sshのコマンド部分を文字列にすればOK。

ssh user@remotehost -T "cat > /remotefile.txt" <<-EOT
Some text
EOT

-Tで擬似端末を無効にしている。

パスフレーズの省略

SSH多段接続時とgit cloneでSSH鍵参照時に、パスフレーズを要求される。毎回要求されるのが手間。これを省略する方法がある。 ~/.ssh/configに以下の設定を記述する。

Host *
 AddKeysToAgent yes
 UseKeychain yes
 IdentityFile ~/.ssh/id_ed25519
  • AddKeysToAgent=yesにすると、ssh-agentの実行時に自動的に鍵を追加する。
  • UseKeychain=macOS専用。OSのキーチェーンからパスフレーズの検索を試みる。
  • IdentityFile=SSH秘密鍵の絶対パス。デフォルトは~/.ssh/id_rsa。

上記3点で自動入力を試みる。 macOSで行う分には上記だけでパスワードは聞かれない。これをリモートでもやりたいなら、ssh-agentに登録が必要。 ログイン時に1回実行してくれたらいいので、ログインシェルの設定の~/.bash_profileに以下を記述。

echo 'ssh-add --apple-use-keychain' >>~/.bash_profile

これで端末の起動時に鍵を自動登録してくれるので、リモートでもパスフレーズを要求されない。

ssh_config

ssh_config(5): OpenSSH SSH client config files - Linux man page

重要な設定・構文がある。

TOKENS

macのman ssh_configに詳しい。

使用可能な指令が限定されている。

HostName (Macのみ)

  • %h=リモートホスト名。Hostの指定部。
  • %p=リモートポート。
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

ssh example.comなどを実行すると、IPアドレスの振り直しなどで、ホストの公開鍵が変わっていた場合、中間者攻撃への対策として失敗する。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
SHA256:.
Please contact your system administrator.
Add correct host key in /Users/z.ken.senoo/.ssh/known_hosts to get rid of this message.
Offending RSA key in /Users/z.ken.senoo/.ssh/known_hosts:1
Host key for [example.com]:3023 has changed and you have requested strict checking.
Host key verification failed.
Connection closed by UNKNOWN port 65535
Connection closed by UNKNOWN port 65535

$HOME/.ssh/known_hostsの該当行を削除すれば解決する。以下のコマンドでも対応してくれる。

ssh-keygen -R example.com

いや、うまくいかない。~/.ssh/known_hostsに以下の該当ドメインの除外設定が必要な模様。

@cert-authority example.com ssh-rsa

sshd(8) - OpenBSD manual pages」に記載がある。

The marker is optional, but if it is present then it must be one of “@cert-authority”, to indicate that the line contains a certification authority (CA) key, or “@revoked”, to indicate that the key contained on the line is revoked and must not ever be accepted. Only one marker should be used on a key line.

...

When performing host authentication, authentication is accepted if any matching line has the proper key; either one that matches exactly or, if the server has presented a certificate for authentication, the key of the certification authority that signed the certificate. For a key to be trusted as a certification authority, it must use the “@cert-authority” marker described above.

https://chatgpt.com/c/67f321e3-3b78-800b-b263-3e7169488367

通常、known_hostsには、接続済みのホストの公開鍵を記録し、次回以降の接続時の確認に使う。ただ、この場合、IPアドレスが動的に変更する場合や、鍵が頻繁に変更される場合に、警告になる。この対策として、@cert-authorityで、同じ行のホスト鍵を署名したCA鍵を信頼する。これにより、同一のCAの複数ホストを一括で信頼する。

curl

HTTPの通信のコマンドラインでの確認でよく使う。

Basic

curl - Tutorial

  • -X: メソッド指定
  • -d/--data-urlencode: リクエストボディー (key=value)を指定。-X POSTも自動指定になる。
curl -H "Content-Type: application/json" -d '{"name":"佐藤", "mail":"sato@example.com"}' localhost:5000/api/v1/users

JSONで送信する場合、ヘッダー指定が必須。

*-F: multipart/formのform指定。

curl -F "coolfiles=@fil1.gif;type=image/gif,fil2.txt,fil3.html"
  http://www.example.com/postit.cgi

@でfilename相当の指定。;でmime typeも指定できる。

@/</;type=自体を送信したい場合、-Fではなく、--form-stringを指定する。

curl: (60) SSL certificate problem: self-signed certificate

Ref: curlで「自己署名証明書」を受け入れるには【curl: (60) SSL certificate problem: self signed certificate】 | LFI.

--insecureオプションを指定すると、localhostなどでの自己署名証明書を許可する。

curl: Failed writing body

pipe - Right After piping to "head"/"tail": "curl: (23) Failure writing output to destination" - Ask Ubuntu

以下のようにhead -n 1を指定するとcurlがエラーを出力する。

curl -H "Content-Type: application/json; charset=utf-8" -H "X-HD-apitoken:$TOKEN"         -d "{\"dbSchemaId\":$dbSchemaId, \"limit\":1, \"offset\":$offset}"         https://$DOMAIN/$ACCOUNT/api/csvexport/version/1.0 | head -n 1
curl: Failed writing body

curlは標準出力に全部書き込めたかチェックしているようで、head -n 1で切り捨てたらcurlはエラーになる。

対策は、curl -sで出力を抑制するとのこと。これで解決。

Teleport

踏み台サーバー (Jump server/Jump host) をよりよく管理するためのサーバーソフトウェア。

アクセスログなどを一元管理できる。商用版とオープンソース版がある。

基本的にteleportのサーバーを一度経由して、各種の踏み台サーバーにアクセスする。経由先が1個増えるが、そのおかげで監査ログを取得できたり、権限などを一括管理できる。

ただ、teleportで監査ログを残すには、基本的にtshを経由する必要があり、既存のIDEなどのssh想定のソフトだと工夫が必要。tsh経由でやったり、rsyncで間にtshを挟むような工夫が必要。

Install

How to configure SSH Certificate-Based Authentication

[Download Teleport: Secure and Easy Infrastructure Access | Teleport] から自分のパソコンのtshをインストールする。

以下の環境変数を設定する。

  • TELEPORT_AUTH:
  • TELEPORT_LOGIN:
  • TELEPORT_PROXY: teleportプロキシーサーバーのアドレス。重要。
tsh

teleportのコマンドラインクライアント。

tsh loginでteleportにログインする。

環境変数

tsh CLI reference | Teleport Docs

  • TELEPORT_AUTH:
  • TELEPORT_LOGIN:
  • TELEPORT_PROXY: teleportプロキシーサーバーのアドレス。重要。

上記3個が特に重要。

ProxyJump+ProxyCommand

How To Use SSH ProxyJump and SSH ProxyCommand

https://goteleport.com/blog/ssh-proxyjump-ssh-proxycommand/

~/.ssh/config のProxyJumpとProxyCommandの違いを整理する。

どちらも中間サーバーを経由したリモートサーバーアクセスの指令。

  • ProxyJump: 最も簡単な方法。OpenSSH v7,5以上で使用可能。中間サーバーでポート転送対応が前提条件。ProxyJumpは内部でProxyCommandを使う。
  • ProxyCommand: ProxyJump搭乗前の方法。中間サーバーを介して標準入力と標準出力を転送して機能。

ProxyJumpの方が現代的だが、ProxyCommandの方が柔軟性が高い。

ProxyJumpの使用例。

ssh -J <jump server> <remote server>ssh -J <jump server1>,<jump server2>,<jump server3> <remote server>

ProxyCommand

ssh -o ProxyCommand="ssh -W %h:%p <jump server>" <remote server>

~/.ssh/configの例。

Host remoteserver

 HostName 192.168.200.200

 User dev

 IdentityFile ~/.ssh/<your_key>

 Port 2048


 ## sample for ProxyJump

 ProxyJump user@<jumpserver>


 ## sample for ProxyCommand

 ProxyCommand ssh -W %h:%p <jumpserver>

ssh remoteserver で<jumpserver> 経由でremoteserverに接続できる。

一般的に、ProxyJumpが推奨される感がある。ただ、teleportを導入している場合、ProxyJump/ProxyCommandを使うと、tshを経由していないのでteleportにログが残らないらしい。

tsh経由ssh

ProxyJump/ProxyCommandを使わない場合、以下の形式でtshを使ってアクセスするのが基本。

tsh ssh 踏み台サーバーホスト名

tsh sshでteleportサーバーが管理している踏み台サーバーが見えるので、そこに接続できる。tshの後のsshは基本的に通常のsshと同じなので、sshの後にsshのコマンドを連鎖でき、対象サーバーにも一発でアクセスできる。

tsh ssh -At <jump host> ssh -A <target host>

-tでttyに繋いで標準入出力を接続。-Aはフォワーディング。ローカルのssh-addの情報などを連携できる。

<jump host>の~/.ssh/configを用意しておくことで、<target host>にホスト名を指定したりできる。

ProxyJump/ProxyCommandと異なり、これだとちゃんとログを残せる。

tsh経由scp

tsh経由の踏み台サーバーへのファイル転送はやや工夫が必要。

tsh scpというコマンドが一応ある。が、これはネストなどには未対応。やる場合、以下のように2回実行になる。

FR=test.file TO=/path/to/test.file
tsh scp $FR <jump host>:$TO; tsh ssh -At <jump host> scp $TO <target host>:$TO

高ではなく、rsyncを使えば一発でいける。

rsync -e "tsh ssh -A <jump host> ssh" ./test.file <target host>:~/

これが基本。

PhpStorm

JetBrains SFTP | Teleport Docs

teleportの公式にマニュアルがあるが、記述が非常に不親切。これだと踏み台サーバーにしかアクセスできない。その先にアクセスできない。

多段SSHの設定を残しておいて、ファイル転送だけrsyncで行う形になる。

PhpStormのSSH configurationsのホスト名がスクリプトの引数に渡されるので、踏み台からAWSにsshでログインするホスト名やパソコンの~/.ssh/configのHostとの一致必要な点に注意する。

USERNAME=
IPV4=
VPCID=
cat <<-EOT >>~/.ssh/config
Host $VPCID
  ForwardAgent yes
  User $USERNAME
  ServerAliveInterval 30
  SendEnv -LC_* -LANG
  ProxyJump $USERNAME@teleport.security:3023
   
Host $USERNAME
    ForwardAgent yes
    ProxyJump $VPCID:22
    User $USERNAME
    Hostname $USERNAME.example.com
    ServerAliveInterval 30
    SendEnv -LC_* -LANG
   
Host $USERNAME.$VPCID
    # for automatic upload by PHPStorm
    LocalForward 22224 $USERNAME.$VPCID:22
    # for XDebug
    RemoteForward 9000 localhost:9000
    ForwardAgent yes
   
Host db-*
  HostName $IPV4
  LocalForward 3307 localhost:22
  ProxyCommand ssh $VPCID -W %h:%p
  ForwardAgent yes
   
Host *
    AddKeysToAgent yes
    PasswordAuthentication no
    User $USERNAME
    ForwardAgent yes
    ServerAliveInterval 30
    IdentityFile ~/.ssh/id_ed25519
    # for macOS
    UseKeychain yes
EOT

こんな感じの多段SSHの設定を用意。 踏み台サーバーにも同じホスト名でアクセスできるように、以下のような内容の~/.ssh/configをまだならば設定しておく。

AWS_HOSTNAME=

IPV4=

VPCID=

tsh ssh -A $VPCID "cat >>~/.ssh/config" <<-EOT

Host $AWS_HOSTNAME

 HostName $IPV4

EOT


rsync executable

rsyncで使用する (-eオプション)、以下の内容のシェルスクリプトを作成して実行権限を付与して任意の場所 (例: ~/project/tsh_ssh.sh) に配置する。

cd ~/project/

cat <<-'EOT' >tsh_ssh.sh

tsh ssh -A <jump host> ssh $@

EOT

chmod +x tsh_ssh.sh


PhpStorm設定

PhpStormで以下を設定する。

  • [Tools]-[Deployment]-[Configuration]
  • [+]-[SFTP]
  • [Create New Server]-[New server name: 任意の名前 (例=rsync)]-[OK]
  • [Connection] タブを以下に設定。
    1. Type=SFTP
    2. SSH configuration=以下を設定。
      1. Host: <ホスト名> (例: ~/.ssh/configと踏み台サーバーの~/.ssh/configのホスト名と同じにする)
      2. User name: ユーザー名
      3. Port: 22
      4. Authentication type: OpenSSH config and authentication agent
    3. Root path=転送先のベース。
    4. [☑️Use Rsync for download/upload/sync]
    5. Rsync Settings=以下を設定。
      1. Shell executable path=tsh_ssh.shのパス (例=~/project/tsh_ssh.sh)
  • [Mappings] タブを以下に設定。
    1. Local path: ローカルパソコンのディレクトリー
    2. Deployment path: /
    3. Web path: /
  • [Settings]-[Build, Execution, Development]-[Development]-[Options]-[Upload changed files automatically to the default server]=[On explicit save action]
    1. ☑️Delete remote files when local are deleted

以上で完了。後は同期したいファイルをPhpStormで開いて、右クリック-[Deployment]-[Upload to]/[Download from] でファイル転送できる。

[☑️Use Rsync for download/upload/sync] のチェックを外せば、rsyncを使わないファイル転送になる。

Wireshark

TLS

Ref: SSL/TLSの復号#1 ~Wiresharkの設定~ | 東陽テクニカ | “はかる”技術で未来を創る | ワン・テクノロジーズ・カンパニー.

Wiresharkで通信パケットを確認する場合、デフォルトでTLSで暗号化されているので、内容がわからない。WiresharkでTLSに対応しておく必要がある。

[Preferences]-[Protocols]-[TCP] を選ぶ。

  • ☑Allow subdissector to reassemble TCP stream
  • ☑Reassemble out-of-order semgemnts

上記をチェックしておく。デフォルトでチェックされていた。

続いて、セッションごとのPre-Master Secretを登録する。

Chrome/Firefoxだと、環境変数SSLKEYLOGFILEを設定すれば、このファイルにTLSセッションキーを出力するので、これをWiresharkで読み込むことで、復号対応する。

以下のコマンド相当で、任意のファイル・場所にログファイルを指定する。

export SSLKEYLOGFILE=/tmp/sslkey.log

Macだとlaunchctlで設定しておくといい。これでWebブラウザー経由の場合は見えるようになる。

Security

DoS攻撃

いくつか対策方法がある。

サーバーログにIPアドレスが残るから、それで攻撃元の国を特定して、該当国を一括アクセス拒否。これが効果あるかもしれない。

攻撃元の国は途上国とかが多いだろうから。IPアドレスは簡単に変更できるが、国を変えるのはたいへんだろう。

バリデーションの実装

基本的に、バックエンドで主にチェックして、フロントエンドはUXの向上目的で実装する。データの重複チェックはDBアクセスが必要だったりするから。また、API経由などフロントがそもそもないケースもある。

ただ、社内システムのような、画面経由でしか使わない。悪者がほぼいないと思われるケースは、フロントエンドでの検証だけでも十分に感じる。

二重送信

submitボタンのダブルクリック、リロード、ブラウザーバック・フォワードなど、フォーム周りで注意が必要な保安要素がある。

  1. ボタン連打
  2. ブラウザーバック
  3. リロード (PRG)

項目ごとにすべき対策が異なる。

連打

基本は、ボタンのsubmitのイベント内でdisabled=trueでの無効化。

似た考え方で、スプラッシュのモーダル表示もあり。これがわかりやすいかもしれない。

$("form").submit(function() {
  var self = this;
  $(":submit", self).prop("disabled", true);
  setTimeout(function() {
    $(":submit", self).prop("disabled", false);
  }, 10000);
});

停止にしたら、二度通せなくなるので、タイムアウトで戻すとよい。

Browser

Chromium

Extension

Chromme系で愛用拡張機能を列挙する。

Profile

https://chatgpt.com/c/67aca944-1fcc-800b-973e-7bf3207b9b91

Webサイトのアカウントを切り替えたい場合、Webブラウザーのプロファイル機能で、アカウント情報を分離できる (Googleアカウントではなくて)。

これでA用、B用など用途ごとにプロファイルを作って、それでセッションやブックマークなどを分けられる。

devtool/開発者ツール

イベントリスナー

要素に設定されているイベントを調べよう - ゆずめも

[Elements]-[Event Listeners]-[handler]-右クリック-[Show function definition] でイベントリスナー関数の定義を確認できる。

イベント監視

How to find out which JavaScript events fired? - Stack Overflow

monitorEvent関数で監視できるらしい。他に、FirefoxのFirebugのlog eventsでも監視できるらしい。

Network conditions

開発者ツールの[Network]タブを開いてリロードしても、[No internet]と表示されることがある。

これはオプション設定の問題。上のツールバーの[Disable cache]の右が[Offline] だとこうなる。これを[No throttling]にすると解決する。クリックミスだと思われる。

Safari

Windows Safari

一応ある。2012-05-09のSafari 5.1.7までWindows版が提供されていた。DL1531。

開発者ツール

PCでスマホサイトを見る方法 – Safari編|東京渋谷のWeb制作会社・ホームページ制作会社|株式会社イー・バード

Safariの開発者ツールは癖がある。

[設定]-[詳細]-[☑️Webデベロッパ用の機能を表示]

[開発]-[レスポンシブデザインモードにする]

スーパーリロード

サポートへようこそ|メールのトラブルやホームページに関するお問い合わせ、 CMS操作方法など各種サポート情報をご案内しております。/各ブラウザでの強制リフレッシュ(スーパーリロード)

Shift-更新ボタン

Other

Tool

いくつかWeb関係の開発で役立つツール集を公開しているサイトがある。

localhost

RFC 6761 で規定。RFC 2606で予約。DNSに登録されることはないため、テスト目的で使用可能。ループバック (送信元にそのまま返す) インターフェイス。

IPv4=127.0.0.1/IPv6=::1とされている。

DB vs. file

https://chatgpt.com/share/67f78855-b640-800b-84c9-ed3ada7fef48

データはアクセス元によって、速度や負荷が異なるらしい。それぞれ特徴がある。

  • ファイル (JSON/php):
  • インメモリーDB: Redis
  • RDB: 排他処理。検索・集計。書込用。

書き込みの最終はRDBとして、そこからよく使うものを、書き込みの少ないものを、インメモリーDBやファイルに引き上げるような感じがする。

Shared Host

Free

無料で使用可能な共用ホスティングサービスがある。

スタードメイン無料サーバー

ドメインをセットで利用する必要があるものの、スタードメインのスタードメイン無料サーバーがけっこういい。

無料レンタルサーバー | スタードメイン - ドメイン取得 100円(税込)~

jpドメインの金額が相場の中では安い方で、それに無料サーバーがついていくる点。

  • ディスク容量 20GB
  • DB 1GB

ただし、SSHやコマンドは使えないので、FTPでWordPressを展開して設置するとか、そういう簡単な使い方だけ。ただ、それでもWordPressでWebサイトを構築するくらいなら十分だと思う。

CORESERVER

メール

情報

ルールが特殊なので注意する。

ゴミ箱に振り分ける場合。

順1 で[./.Trash] を指定

順2

  • 条件:  [.*]
  • 処理:  ./、に振り分ける

条件部分には正規表現が使えるように見える。

破棄にしないといけない。転送する場合、カスタムフィルターの中に転送を入れる。条件を.*にする。

カスタムフィルターにくせがある。

  • エスケープ(\を前置する)が必要な文字は「'」「"」「|」「`」「~」「?」「!」

Value Domain ネットde診断 byGMO

2024-06-07 Friからバリュードメイン系の利用者に無料で提供しているセキュリティー診断ツール。

CGI

CORESERVERでのCGIの設定方法がある。

CORESERVERのFastCGI版PHPとCGI版PHPの設定方法
項目 FastCGI CGI
バージョンの変更 管理画面 .htaccess内の

AddHandler application/x-httpd-phpcgiXX .php

設定ディレクトリー /virtual/<username>/public_html/.fast-cgi-bin/
CGIの実行ファイル phpXX.fcgi phpXX.cgi
PHPの設定ファイル phpXX.ini php.ini
設定の反映タイミング バージョン切替時 即時

~/public_html/.fast-cgi-bin/のphpXX.fcgi phpXX.cgiがCGIの実行ファイル。このファイルか最後の行のexecのパスを変更すると、自前コマンドに変更可能。

FastCGIは管理画面からバージョンを変更したタイミングで反映される。ただ、ファイル拡張子が.phpじゃないとこのFastCGIが実行されない模様。

CGIは.htaccessに以下の内容を記述してCGI板PHPのバージョンを指定する。

AddHandler application/x-httpd-phpcgiXX .php

cgiのファイルには実行権限が必要。

chmod +x py.py

拡張子がないとダメな模様。加えて、.htaccessに以下の記述。

AddHandler cgi-script .py

これでpy.pyで動作はする。

拡張子じゃなくてファイル名で実行したい場合、SetHandlerでしていする (AddType, AddHandler, SetHandlerの違い – senooken JP)。

<FilesMatch py$>
    SetHandler cgi-script
</FilesMatch>

これでpyでもアクセスできる。

FastCGI版の場合、以下のような設定でファイル名でマッチさせれば実行できそうな気もするが。

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>

500

<FilesMatch gnusocial$>
        SetHandler application/x-httpd-php
</FilesMatch>

pythonがphpとして認識され、テキストがそのまま表示される。

SetHandler fcgid-scriptにしたらFastCGIで動作する。プログラムがFastCGI対応になっている必要がある。

<FilesMatch gnusocial$>
        SetHandler fcgid-script
</FilesMatch>

Analytics

Exam

## About

https://gnusocial.jp/notice/4506679

### 全般

- マーケティング・ビジネス実務検定

- IMA検定

- Web検定

- ネットマーケティング検定

### 解析系

- ウェブ解析士

- GAIQ

- 統計検定

- Webアナリスト検定

GAIQが無料だしどうせ使うからいいかな。

https://wacul-ai.com/blog/access-analysis/google-analytics-method/gaiq/

https://www.plan-b.co.jp/blog/seo/12792/

## URL

- https://ceres-inc.jp/business-tips/recommended-webmarketing-shikaku/

- https://mynavi-creator.jp/blog/article/qualification-for-web-marketer

- https://www.icloud.co.jp/article/exam/features-and-5-acquisition-benefits.html

- https://digitor.jp/textbook/web-analytical-qualification/

Tool

サイト分析用のツールがいくつかある (2023年ブログランキング!おすすめブログランキングサイト比較【一般人向け】)。

  • SimilarWeb
  • Ubersuggest
  • ahrefs
  • Googleキーワードプランナー

閲覧数取得

出典: GoogleAnalyticsで自サイトの人気記事ランキングを表示する方法 | アフィリエイトJAPAN

  • [行動]-[サイトコンテンツ]-[全てのページ]
  • [表示する行数]=5000
  • [エクスポート]=TSV

流入元特定

会員登録画面の流入元探索方法について - Google アナリティクス コミュニティ」どのページから会員登録があったか、会員登録に結びつく記事は非常に重要。

こんにちは。

探索レポートでユーザーセグメントを作成する集計方法はいかがでしょうか。

・自由形式レポートを作成

・セグメント作成 > ユーザーセグメント

・条件は page_view > パラメータ page_location > 含む:会員登録画面のURL を指定

・「会員登録画面閲覧ユーザー」などセグメント名をセットして保存

・探索レポートにセグメントを適用

・ディメンション:セッションの参照元 / メディア、ランディング ページ + クエリ文字列

・指標:セッション

ご確認よろしくお願いいたします。

※ページ閲覧の発生しなかったセッションはランディングページが (not set)になります。

 開きっぱなしのタブから再訪問するセッションなどが該当します。ご参考までに。

PMProでも似たような回答。

Google Analytics 4 can track ecommerce conversions and then assign page value to posts that were a part of their conversion path for that engaged session.

Server

httpd

Apache HTTP Server

About

httpdの利用可能な情報。

https://chatgpt.com/c/6761f851-df0c-800b-86e9-1624b458d66d

# 使用可能な指令一覧
apachectl -L
httpd -L

# 使用可能なモジュール一覧
apachectl -M
httpd -M

.htaccessで使用可能な指令の一覧。

.htaccessで使用可能な指令一覧 – senooken JP

Operation

サーバーの稼働や状態確認などで重要な操作がいくつかある。systemd前提。

ログ・状態確認。

sudo systemctl status apache2

sudoをつけないと詳細ログを確認できない。

sudo systemctl restart apache2
sudo systemctl start apache2
sudo systemctl stop apache2

Access Control

DoS攻撃対策などで重要な設定。

mod_authz_core/mod_authz_hostがコアモジュール。mod_rewriteも関係ある。

基本構文は以下。

Require host <address>
Require ip <ip address>

1番目の形式はドメイン名。2番目はIPアドレス。部分マッチする。マッチしたもののアクセスを許可する。

Requireの直後にnotを指定してアクセス禁止にできる。こちらが重要。

mod_cgi

mod_cgi - Apache HTTP Server Version 2.4

CGIプロトコルのApacheモジュール。cgi-scriptにハンドラーを割り当てるとCGIとして扱う。

mod_fcgid

mod_fcgid - Apache HTTP Server Version 2.5

FastCGIプロトコルのApacheモジュール。AddHandlerかSetHandlerでfcgid-scriptハンドラーに割り当てられると、FastCGIとして処理される。

プログラム側もFastCGIに対応している必要がある。

Error

sudo systemctl status apache2
● apache2.service - The Apache HTTP Server
     Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
    Drop-In: /etc/systemd/system/apache2.service.d
             └─privatetmp.conf
     Active: failed (Result: exit-code) since Fri 2024-12-06 15:09:28 JST; 12s ago
       Docs: https://httpd.apache.org/docs/2.4/
    Process: 38461 ExecStart=/usr/sbin/apachectl start (code=exited, status=1/FAILURE)

Dec 06 15:09:28 z-ken-senoo apachectl[38464]: AH00548: NameVirtualHost has no effect and will be removed in the next release /etc/apache2/ports.conf:8
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: [Fri Dec 06 15:09:28.259153 2024] [core:warn] [pid 38464] AH00117: Ignoring deprecated use of DefaultType in line 122 of /etc/apache2/apache2.conf.
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: AH00112: Warning: DocumentRoot [/home/gree/frontend/greenet/htdocs_net] does not exist
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: AH00526: Syntax error on line 7 of /etc/apache2/conf-available/rewrite-greenet.conf:
Dec 06 15:09:28 z-ken-senoo apachectl[38464]: RewriteRule: unknown flag 'UnsafeAllow3F'
Dec 06 15:09:28 z-ken-senoo apachectl[38461]: Action 'start' failed.
Dec 06 15:09:28 z-ken-senoo apachectl[38461]: The Apache error log may have more information.
Dec 06 15:09:28 z-ken-senoo systemd[1]: apache2.service: Control process exited, code=exited, status=1/FAILURE
Dec 06 15:09:28 z-ken-senoo systemd[1]: apache2.service: Failed with result 'exit-code'.
Dec 06 15:09:28 z-ken-senoo systemd[1]: Failed to start The Apache HTTP Server.
AH00548: NameVirtualHost has no effect and will be removed in the next release /etc/apache2/ports.conf:8

NameVirtualHost指令が廃止予定なので、行を削除して対応する。

AH00117: Ignoring deprecated use of DefaultType in line 122 of /etc/apache2/apache2.conf.

DefaultTypeはnone以外意味がなく、警告表示になる模様。

.htaccess

directive

.htaccessで使用可能な指令一覧 – senooken JP

.htaccessで使用不能なよく登場して誤解する指令を整理しておく。

  • Alias
  • ScriptAlias
  • Directory/DirectoryMatch
  • Location/LocationMatch

逆にOKなもの。

  • Files/FilesMatch

E-mail

[サーバーIPがブラックリストに載ってメール送信エラーになるのを解除する方法]

MailHog: Go言語製のメールサーバーソフト。

Debian

PHP8

[How To Install PHP 8.0 on Debian 11/10/9 | ComputingForGeeks](https://computingforgeeks.com/how-to-install-php-on-debian-linux/)

Debian 11の場合、PHP 8には外部リポジトリーが必要なので追加する。

sudo apt update

sudo apt install -y lsb-release ca-certificates apt-transport-https software-properties-common gnupg2

PHPパッケージを追加する。

echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/sury-php.list

wget -qO - https://packages.sury.org/php/apt.gpg | sudo apt-key add -

sudo apt update

これでPHP8を参照できるので、インストールする。

sudo apt install php8.2

[How to Switch between Multiple PHP Version on Debian 12/11/10 – TecAdmin](https://tecadmin.net/switch-between-multiple-php-version-on-debian/)

インストールしたら、PHPのバージョンを切り替える。

a2dismod php7.4

a2enmod php8.2

sudo systemctl restart apache2

php 8.2にするとこういうエラー。

[Sat Sep 02 11:31:02.558029 2023] [php:error] [pid 25644] [client 133.106.38.37:57181] PHP Fatal error:  Uncaught Error: Undefined constant "DB_DATAOBJECT_ERROR_NODATA" in /var/www/gnusocial/public/index.php:104\nStack trace:\n#0 [internal function]: handleError()\n#1 {main}\n  thrown in /var/www/gnusocial/public/index.php on line 104

念のためdockerで起動を試みましたが、同じくトップ画面を開くと同じエラーになります。

<https://notabug.org/gnusocialjp/gnusocial/src/main/docker/development> にDockerでの起動方法があります。`docker compose up -d` を実行するだけでlocalhostでアクセスできます。

私とあなたとの環境の違いを排除したいので、dockerのインストールだけ頑張って、それでdockerでも簡単に動作確認してくれませんか?

alternative

Ref: DebianAlternatives - Debian Wiki.

OS内でバージョン違いのプログラムを管理するための仕組みがある。それがupdate-alternativesコマンド。

sudo update-alternatives --display vi
sudo update-alternatives --config vi

オプションとコマンド名を指定することで、現在の実体と更新ができる。

XAMPP

ポート番号変更

Xamppでポート競合を防ぐ方法 #PHP - Qiita

XAMPP Control PanelのConfigから変更可能。

phpmyadminはConfigのphpmyadminで、Servers.portを追加する。

Vim

vimdiff

2 つのファイルの差分を取る・マージする (vimdiff, vim -d) - まくまくVimノート

vimのdiff機能。ファイル同士の差分のチェック、マージで簡易的に使える。

diffモードで起動

vim -d <file1> <file2>
vimdiff <file1> <file2>

起動中のdiffモード

:diffs[plit] <file> " 上下分割
:vert[ical] diffs[plit] <file> " 左右分割
:diffthis " バッファー同士

移動

  • [c=前の差分に移動。
  • ]c=次の差分に移動。

マージ

  • dp=diff put。自分の内容を片方に反映。
  • do=diff obtain。自分の内容に片方を反映。

Other

Async

https:/github.com/skywind3000/asyncrun.vim

asyncrun.vimは1個のバックグラウンド処理しか対応していない。

https://github.com/skywind3000/asyncrun.vim/issues/12

vim-dispatchならいけるのか?

Binary

vim-jp » Hack #133: バイナリファイルを編集する

grep

非同期でgrepする方法。

https://superuser.com/questions/861783/how-to-run-a-grep-in-vim-asynchronously

https://www.reddit.com/r/vim/comments/5ses2e/async_grep_in_vim_8/

Vim 8の非同期APIはプラグイン用。

* https://github.com/mhinz/vim-grepper

* https://github.com/skywind3000/asyncrun.vim

* https://github.com/tpope/vim-dispatch

https://wonderwall.hatenablog.com/entry/2017/10/09/210000

asyncrun.vimでやるのがよさそう。

AnsiEsc

* https:/unix.stackexchange.com/questions/444226/how-to-make-vim-interpret-escaped-characters-as-colors

* https:/superuser.com/questions/358409/how-can-i-tell-vim-to-show-ansi-escape-codes-properly

本家は太字に対応していないのでこちらがいいかな。

- https:/github.com/powerman/vim-plugin-AnsiEsc

ただし、こちらはgvimでクリック時にカーソル位置がずれる。

program

C

ワシのVimプラグインは百八式まであるぞ - daisuzu's notes

【C/C++】

     87. a.vim

        C/C++のヘッダとソースを切り替えます。

     88. c.vim

        C/C++のテンプレートやイディオムの入力をサポートしてくれます。

     89. CCTree

        cscopeを使って関数のコールグラフを表示してくれます。

     90. Source-Explorer-srcexpl.vim

        ソース解析ツール、Source InsightのVim版です。

     91. trinity.vim

        taglist, srcexpl, nerdtreeを同時に起動して

        VimがIDE画面のような画面になります。

     92. cscope-menu

        cscope用のメニューを表示してくれます。

     93. gtags.vim

        gtagsを使ってファイルを開けます。

     94. DoxygenToolkit.vim

        Doxygenコメントの入力をサポートしてくれます。

Visual Studio Code

Keybind

矩形選択

Ref: VS Codeの矩形選択と矩形貼付の操作方法 - mito’s blog.

  • s-alt-クリック
  • c-s-alt-矢印

ジャンプ

  • 括弧ジャンプ: C-S-\

Config

Default terminal

Ref: bash - Change the default terminal in Visual Studio Code - Stack Overflow.

[F1]-[Terminal: Select Default Profile]

cscope

cscope用のプラグインが何個かある。

scope4codeのほうがいろいろできそうだが、うまく動作しなかった。使い方がよくわからない。

cscope-codeはシンプルだが動作した。こちらを当分使うことにする。

Macの場合、control-. sのように、control-.の後に、controlを話してsを押すと発動する。カーソル下のシンボルしか使えない感じなのがネック。まあいい。

Vim

VSCodedでVimのキー操作を使うためのプラグイン。これが一番人気。いや、Vimのエミューレーターは中途半端な感じだから使わないほうがいいかな。

Extension

CSS

Tailwind CSS IntelliSense

PHP

Laravel Blade Snippets

PHP Intelephense

Ref: PHP Intelephense - Visual Studio Marketplace.

VSCodeのPHPの補完拡張として人気が高い。

Quick Start

設置後、しておくべき設定がある。

  • Go to Extensions.
  • Search for @builtin php
  • Disable PHP Language Features. Leave PHP Language Basics enabled for syntax highlighting.

VSCodeの [PHP Language Features] を無効にしておくとのこと。

後は、.php以外の拡張子でPHPファイルがあれば、関連付けを追加するとか。

Module

peclなどPHPの標準モジュールで一部認識できないものがある。

php - Undefined type 'Imagick' in VSCode's intelephense - Stack Overflow」にあるように、そういう場合は [Settings]-[Stubs] で追加するとよい。

Coding

Ref: VSCode で PHP 開発するならインテリセンス最強の intelephense を使おう | 株式会社ビヨンド.

intelephenseでコード補完を認識しやすい書き方というのがある。

まず、型をつけられるものはつける。

function superMethod()
{
    /** @var AwesomeService $awesomeService */
    $awesomeService = $this->app->make(AwesomeService::class);
    $awesomeService->awesomeMethod();
}

ローカル変数も型名を指定する。これをしないと、インスタンスでコード補完が効かない。

Other

Remote

【WinSCPはもう不要?】VS Codeのダウンロード/アップロード機能が便利すぎる!! | マスクロドットコム

Visual Studio Code Remote Development

公式拡張機能のVS Code Remote Developmentを使うと、リモートファイルをVS Codeで開いて、ドラッグドロップでファイル送受信ができるらしい。

PhpStorm

Jump

includeなどで参照しているファイルパスのファイルを開く方法がいくつかある。

  • C-b
  • C-LButton
  • C-N/C-O でファイルを開いてファイルパスを貼り付け。

認識できないことがあるので3番目が汎用的。

Encoding

パス単位で文字エンコーディングを設定可能。

[PhpStorm]-[Settings]-[Editor]-[File Encodings] から行う。

Scratch

【New Year Calendar】君はPhpStormのScratch機能を知っているか #NewYearCalendar - Qiita

メモなどの一時ファイルの作成機能。

[File]-[New Scratch File] からファイル形式を選んで作る。困ったらMarkdownで良いだろう。

作成したScratchファイルは [Project]-[Scratches and Consoles]-[Scratches] に格納される。

矩形選択

複数のカーソルと選択範囲 | PhpStorm ドキュメント

方法がいくつかある。

  • Cmd-Shift-8
  • Option-Shift-Middle

Git

Gitツールウィンドウ

C-9か左下のGitマークを選ぶとGitツールウィンドウの表示になる。ブランチとコミットログが表示される。ここから右クリックを使ってブランチ間の比較などができたりする。

ブランチ比較

コードレビューなどでよく使うブランチ同士の比較。

まず現在ブランチを比較対象ブランチに変更しておく。

[Git]-[Branches]-比較対象ブランチ-[Compare with]

これで上下に画面分割して、それぞれのブランチで固有のコミットログの一覧が表示される。派生元と派生先があるならば、片方が空になる。違うブランチ同士のマージ用に、こういう作りになっていると思われる。

差分ファイル一覧を見るには、右側の変更ファイルペーンでC-aを選ぶ。変更のある全ファイルのリストが表示される。

他に、Gitツールウィンドウを開いて、コミットログで右クリック-[Compare with Local]を選ぶとローカルと対象コミットとの比較になる。これがわかりやすい。

ただ、基本は現在ブランチか、現在のワーキングツリーとの比較になる。現在ブランチを変更しておくのが基本になる。そこだけ押さえておけば、まあなんとか使えそう。

元ファイルオープン

差分ビューで差分チェック中に、シンボルや型定義などの確認で元ファイルを開きたいことがある。ジャンプ方法がある。

左上の [Jump to Source C-Down] の鉛筆マークを選ぶ。これでエディター側で元ファイルを開ける。

サブディレクトリー

PHPStormで親のGitリポジトリーの下に、子のGitリポジトリーのディレクトリーがある場合、親ディレクトリーのGitしか認識してくれない。

認識してくれる方法がある模様。

Gitのマルチリポジトリー機能を使うらしい。

[Settings]-[Version Control]-[Directory Mappings]-[+]

以下を選択して [OK] を選ぶ。

  • ◉Directory: Git子ディレクトリーのパス
  • VCS: Git

これで対象ディレクトリーを右クリックでGitを選ぶと良い模様。

Blame

行番号のところを右クリック-[Annotate with Git Blame] で行単位の修正履歴を表示できる。

  • Annotate Revision: 現在の変更コミットを表示。
  • Annotate Previous Revision: 前回のコミットの表示。

過去の修正履歴の調査で役立つだろう。

Search

https://chatgpt.com/c/6798762a-2c2c-800b-8dab-4a7b8252fe7b

PhpStormの便利ショートカットキー~検索編~

PHPStormでは検索がいくつかある。

ファイル名検索

  • Mac以外=C-N
  • Mac=C-O

スペース区切りでAND検索になる。パスを含めると、ディレクトリーも絞り込める。

Search Everywhere

Shift2回押下。

  • C-f: ファイルない検索。
  • C-F: 全体検索。

Other

Window

プロジェクトを開く、移動、閉じる | PhpStorm ドキュメント

ペーンを分離したり移動したりできる。

ペーン右上[…]-[View Mode]-[Window] を選ぶと、別画面に分離できる。並列時に重宝する。

ディレクトリーの無視

除外されたファイルとフォルダー | PhpStorm ドキュメント

PhpStormでコーディングで使用しないディレクトリを除外してパフォーマンスを改善する | プロガジ.DEV

シンボリックリンクだったりして、同じファイルが違うパスで表示されることがあって困る。ディレクトリーを除外する。

右クリック-[Mark Directory as]-[Excluded] を選ぶ。

Bookmark

ブックマーク | PhpStorm ドキュメント

よく参照するコードの行・ファイル・ディレクトリー、をブックマークに登録して、迅速にアクセスできる。

  1. 左端のプロジェクトツールウィンドウ (C-1) で対象項目を右クリック-[Bookmarks]-[Add Bookmark]
  2. [View]-[Tool Windows]-[Bookmarks] を選ぶと、、サイドバーにBookmarkのボタンが表示される。

Web Browsers and Preview

ウェブブラウザーとプレビュー | PhpStorm ドキュメント

PHPファイルの編集時に、右上にプレビューボタンが表示されて邪魔。以下の設定で非表示にできる。

[Cmd-,]-[Settings]-[Tools]-[Web Browsers and Preview]-[Show browser popup in the editor]-[▫️For HTML files]

ファイル差分

ファイルの差分ビューアー | PhpStorm ドキュメント

ファイル差分の閲覧機能がある。

右クリック-[Compare with Clipboard]

これが手っ取り早い。

PEARの認識

1 pear show-configでphp_dir (=/usr/share/php/) を確認する。

2 このディレクトリーをローカルマシンに保存する (~/projectなど任意の場所)。既存プロジェクトの外に配置した方が都合良いだろう。

3 PHPStormの[Settings]-[PHP]-[include Path] で2で保存したディレクトリーを指定する。

.bashrc

bash - .bashrc not sourced on Intellij IDEA's terminal - Stack Overflow

いくつかの理由で、IntelliJは標準ではBashを対話モードで起動しない。だから.bashrcを読み込まない。

ただし、これは設定で変更可能。

[Settings]-[Tools]-[Terminal]-[Shell path] に-iを追加する。だめなら、--loginとか。

終端スペースの自動除去

PhpStorm removing tabs/spaces on every save - Stack Overflow

PhpStormでファイルを開いて保存すると、勝手に終端スペースを削除する。デフォルトでそういう設定になっている。

[Settings/Preferences]-[Editor]-[General]-[Remove trailing spaces]=on

PIM

Personal Information Manager - Wikipedia

PIMという個人情報管理用アプリの分類がある。

  • カレンダー
  • アドレス帳
  • 電子メール
  • タスク管理
  • メモ帳
  • 音声メモ
  • 電卓
  • 時計
  • 電子辞書

E-mail

General

docomoのメール

MozillaZine.jp フォーラム • トピック - 特定のメールだけ,画像が定位置に表示されません。

docomo関係のメールを受信すると画像などがうまく表示されず、ハイパーリンクも機能しない。

[View]-[Message Body As]-[Simple HTML] にすると、ハイパーリンクなどは機能する。

メールヘッダーの問題の模様。

- Content-Type: multipart/mixed; boundary="=_**********"
+ Content-Type: multipart/related; boundary="=_**********"

上記のように変更するとうまく表示されるらしい。


winmail.dat

winmail.dat変換ツール(インストール不要)

MS outlookなどで使われる添付ファイルの形式。

Naming
RFC
  • webmaster
  • support
  • info
  • service
  • pr
  • billing
  • 氏名

売上をアップするメールアドレス、商機を失うメールアドレス | マイナビニュース

infoやwebmasterなど企業サイトが備えるべきメールボックスのルール、ご存じですか? | 編集長ブログ―安田英久 | Web担当者Forum

rfc-jp.nic.ad.jp/rfc-jp/RFC2142-JP.txt

SuperTAINS News No.23 [Page.5]

【Mail】メールアドレス作成のガイドライン(RFC2142) – fumidzuki

公開用のメールアドレス。何にしようか考えていた。

RFC 2142でいくつか推奨されている。

info@ support@ answer@ inquery@ contact@ pubic@

contact@がやっぱり一番しっくりくる。info@ support@はRFC 2142にあるけど,これはビジネスより,サービスに紐付いたもの。個人でやる分にはサービス関係ないから,これは違う。publicも悪くはないのだけど,あまり一般的ではないか。

develop

GNU social JP管理人 (gnusocialjp@gnusocial.jp)'s status on Saturday, 08-Oct-2022 23:13:28 JSTGNU social JP管理人GNU social JP管理人
使用するメールアドレスに悩みます。GitのメールアドレスはGitのホスティングサービスに掲載され一般公開されます。

メーリングリストのメールアドレスも、返信方法によって引用されアーカイブで一般公開されます。

どう使い分けるのがよいでしょうか?案↓
GNU social JP管理人 (gnusocialjp@gnusocial.jp)'s status on Saturday, 08-Oct-2022 23:20:04 JSTGNU social JP管理人GNU social JP管理人
  1. develop@domainのようなアドレスで共有
  2. develop@, ml@ で用途別
  3. contact@ で一般公開用で共有
開発用のメールなので、1がいいですかね。仮に漏洩しても開発関係経由というのがわかるので。

1がいいと思う。

category

目的に応じて使い分けたほうがよさそう。

メールアドレスを何個ぐらい使い分けたら安全・快適に過ごせるのか - Dr.ウーパのコンピュータ備忘録

メールアドレス流出時の被害防止

不審なメールの検知

必要な数

  • 銀行・証券会社
  • 知り合い
  • ショッピングサイト

その他

  • Webサイトなどの公開用
  • 本名でのやり取り
  • ニックネーム
  • 金銭のやり取りのないサービス登録
  • 金銭のやり取りのあるサービス登録
  • 登録にメールアドレスが必要だけど,そんなに使っていないメール

メールアドレスの種類

  • フリーメール
  • プロバイダーメール
  • 独自ドメイン

メールアドレスの種類とアフィリエイトにおける3つの使い分け方法 | アフィリエイト

  • サービス登録用
  • メルマガ購読用(捨てアド)
  • メインアドレス

メールアドレスの使い分けかた(前編) - 学習する機械、学習しない人間

メールアドレスの使い分けかた(後編) - 学習する機械、学習しない人間

これらを考えてどういう名前で何個用意するかを考える。

とりあえずメインで使うmainというアドレスを一つ用意する。残りをどうするか。

Webサイト公開用にcontact

  • main: メインで使うメール。人に直接教えるときや,お金が絡む場合,ショッピングサイトなど実名が求められるような重要な内容にはこれ。こちらから送信するときもこれ。相手の顔が見えているとき。
  • contact:受信専用,公開用。問い合わせ用。なんかフォーラムやブログのコメント欄やcontact usなどにこちらから問い合わせる時なども。相手の顔が見えないときなど。
  • service: 基本的に受信専用,たまに返信。Webサービス登録用。
  • recruit:就職活動用。就職サイトとか転職エージェント,企業とやりとりするときはけっこうメール来るから。
  • job: 個人事業、仕事用、不動産は事業なのでこちら。
  • money: 金融機関登録用。銀行、証券会社、クレジットカード会社、決済会社・サービス。
  • shop/store: ショッピングサイト、個人間売買サイト。
  • ユーザー名: メールアドレスの@以前はユーザー名とみなされることがあるので、ユーザー名のアドレスも用意しておくとよさそうだ。


こちらから送信するときのメールアドレス。

Webサービスに登録するときどうするか。不動産屋さんとか人に教えるときはどうするか。アフィリエイトとかドメインとか実名が求められるときはどうするか。

gmailの+を考える。gmailでは+や.をつけると無限にアドレスをつけられる。ただし,受信は+のないメール。

ただし,gmailの+は使えないときがある。@以前の部分をユーザー名とみなして,+を無効な文字とみなすサービスがある模様。

ネットではがきが印刷~郵送できるポスコミ【1枚から注文OK】

https://www.tomtop.com/もだめ。

今まで使ってきたメールとはどうやりくりするか。

Thunderbirdでやる場合,Archiveするときに既読とメールのコピーを行う。

他のアドレスのメールはmainに転送するようにしておいて,mainのメールアドレスで確認。

最終的にThunderbirdでArchiveを実行したら,宛先のメールのフォルダーに同じ内容が既読状態でコピーされることにする。

このようなフィルターを作っておく。受信時にコピーしてしまうと,未読状態でコピーされてしまうか,受信した瞬間に既読状態になってしまい,見逃す可能性が高い。

Manage Identitiesで返信時に受信したアドレスで返信できるように登録しておく。

Mozilla Thunderbird

プロファイルの統合

ImportExportToolsでデータ移行するというのが手堅い。一括操作を念頭に置いた機能になっている。数が少ないならば、emlファイルをドラッグドロップで取り込むこともできる。

Gmail

未読メール件数

Gmailの未読メール件数をタブに表示させる方法 | ライフハッカー・ジャパン

[設定]-[詳細]-[未読メッセージ アイコン]=[◎ 有効にする]

デスクトップ通知

[設定]-[全般]-[◎ メール通知(新規メール) ON]