c言語 デバック文の出力方法

(1)DEBUG_PRINT()の関数をマクロ定義します。#define DEBUG_PRINT(…) printf(“%s(%d) %s:”, __FILE__, __LINE__, __func__),printf(“Debug: %s\n”, __VA_ARGS__)

※1)「ファイル名」、「行番号」、「関数名」はプリプロセッサによって標準で定義されたマクロを使います。
項目     マクロ名            出力指定子
ファイル名  __FILE__             %s
行番号   __LINE__             %d
関数名   __func__、または__FUNCTION__ %s

※2)DEBUG_PRINT(…) の可変個数の引数”…”は、”__VA_ARGS__”に展開されます。

(2)条件コンパイルを利用することで、出力を無効化します。「DEBUG」が定義されている場合、マクロは”DEBUG_PRINT”で定義したマクロが展開され、「DEBUG」が定義されていない場合、マクロは何も展開しません。

debug_sample1.c

//  デバッグ機能の有効/無効
#define DEBUG
#include <stdio.h>

#ifdef DEBUG
#define DEBUG_PRINT(...) printf("%s(%d) %s:", __FILE__, __LINE__, __func__),printf("Debug: %s\n", __VA_ARGS__)
#else
#define DEBUG_PRINT(...)
#endif

int main() {
    DEBUG_PRINT("Starting program...");
    // rest of the program
    return 0;
}

実行例

(3)DEBUG_PRINTの引数にエラー番号を追加

debug_sample1.c

//  デバッグ機能の有効/無効
#define DEBUG

#include <stdio.h>

#ifdef DEBUG
#define DEBUG_PRINT(errno,...) printf("[ERRNo:%d]%s(%d) %s:",errno, __FILE__, __LINE__, __func__),printf("Debug: %s\n", __VA_ARGS__)
#else
#define DEBUG_PRINT(...)
#endif

int main() {
    DEBUG_PRINT(100,"program error...");
    // rest of the program
    return 0;
}

end

Web3.0の概要

1.Web3.0とは
 インターネットの活用において、Web1.0(1990年~2000年)が主に情報の閲覧、Web2.0(2000年~)は中央のサービス提供事業者の情報管理を介在した情報の閲覧と発信、Web3.0(2010年~)では中央のサービス提供事業者を介在することなく、利用者間で情報を発信と閲覧が可能となる情報分散型の仕組みが使われる。
 分散型管理技術としてはブロックチェーンが使われ、中央で情報を管理しなくても情報の改ざんなどが困難になる。

2.Web3.0が出てきた背景
 従来のサービス提供事業者による中央管理のサービスでは、
 ・情報の漏えいリスク
 ・サービス停止に伴い、情報資産が活用できなくなるリスク
 などがある。

3.Web3.0の事例
 現在、web3を活用したサービス例として下記のものがある。
(1)WebブラウザのBrave(ブレイブ)
 Brave(ブレイブ)は、Brave Softwareによって開発されているウェブブラウザで、広告とトラッカーをブロックする機能を標準装備し、ユーザーのプライバシーの保護、そして高いパフォーマンスを実現。(wikipediaから引用)

(2)NFTマーケットプレイスのOpenSea(オープンシー)
 NFT(Non-Fungible-Token:非代替性トークン)とは、アート作品や音楽作品、イラストなどあらゆるデジタルデータに、暗号資産に用いられるブロックチェーンを組み合わせることで作品としての唯一性を持たせる技術であり、これらを使ったオンラインマーケットプレイスである。

(3)NFTゲームアプリのMy Crypto Heroes(マイクリプトヒーローズ)
 2018年11月30日に日本初のNFTゲームとしてリリースされた。

(4)分散型ソーシャルグラフのCyberConnect(サイバーコネクト)
 CyberConnect(サイバーコネクト)は分散型のソーシャルグラフプロトコル。
 ソーシャルグラフプロトコルは、複数の人間の相関関係や人間同士の結び付きを意味する概念でSNSにおける人間関係のネットワークを可視化したものを指す。

4.Web3.0取り組みに関する国の政策など
(1)省内横断組織として「大臣官房Web3.0政策推進室」の設置
 Web3.0関連ビジネスに対する国内の事業環境整備を目的に設置。
 ブロックチェーン技術、NFT(Non-Fungible Token、非代替性トークン)、DAO(Decentralized Autonomous Organization, 分散型自律組織)など新たなビジネスに対応できるように税、会計、法制度、知財、消費者保護、標準などの観点から国内制度を整備する必要がある。
(出典)
https://www.meti.go.jp/press/2022/07/20220715003/20220715003.htm  

 Web3.0の利用拡大に向け、国内ではトークンを用いた資金調達や税処理、DAO運営などに関し、既存の制度が未対応であることが課題として挙げられる。また、ユーザ自身が秘密鍵を扱う方法とそのリスクを認知する必要もある。ブロックチェーンのさらなる性能改善だけでなく、事業展開に関わる法律や税制度の改正、消費者保護の観点から健全な市場形成のための利用環境整備が求められる。
 ブロックチェーンに関連したサービスすべてが真にWeb3.0に求められている特徴を有するとは限らない。今後Web3.0の活用を考える上で、技術への理解とWeb3.0を掲げるサービスの実態を把握することが肝要である。
(引用)
 Web3.0トレンドを俯瞰する
 ~ブロックチェーン技術が実現する次世代のインターネット~
 2022年8月15日 株式会社日本総合研究所 先端技術ラボ
 https://www.jri.co.jp/MediaLibrary/file/column/opinion/pdf/13626.pdf

5.ブロックチェーンの基本
(本サイト内のコンテンツ)
ブロックチェーンの基本

ブロックチェーンの基本

1.ブロックチェーンとは
 Web3.0では中央のサービス提供事業者を介在することなく、利用者間で情報を発信と閲覧が可能となる情報分散型の仕組みが使われるが、ブロックチェーンは分散型管理技術として使われ、中央で情報を管理しなくても情報の改ざんなどが困難な仕組みが可能になる。

2.ブロックチェーンの事例
 仮想通貨の他、現在、ブロックチェーンを活用したサービス例として下記のものがある。
(1)NFTマーケットプレイスのOpenSea(オープンシー)
 NFT(Non-Fungible-Token:非代替性トークン)とは、アート作品や音楽作品、イラストなどあらゆるデジタルデータに、暗号資産に用いられるブロックチェーンを組み合わせることで作品としての唯一性を持たせる技術であり、これらを使ったオンラインマーケットプレイスである。

3.ブロックチェーンの仕組み
(1)背景
 ブロックチェーンはWeb3.0の分散型管理の基本的な技術となっており、サービス提供者の存在を前提としないインターネット上で取引などの情報を安全に扱うために、なりすましや改ざんをどう防ぐか、二重支払いをどう防ぐかという問題に対処している。
 ブロックチェーンは、P2Pネットワーク、ハッシュ、電子署名、コンセンサスアルゴリズムの4つの技術を応用することで上記の問題の解決を図ってい

(2)ブロックチェーンのメリットとデメリット
・メリット
 分散型のためシステムダウンせず、改ざんが非常に困難な仕組みを持っている。
 取引記録の書き換えや消去ができないため、公的な記録を残したい場合には最適。
・デメリット
 一度記録した個人情報は二度と削除できなくなってしまうだけでなく、暗号化された状態ではあるもののネットワーク上の全ての参加者に情報が行き渡ってしまう。
 合意形成に時間がかかる。
 ブロックチェーンの利用が進むに従い取引履歴として保持するデータ量が増え通信量が増える。

(3)ブロックチェーンの種類
 ブロックチェーンには誰でも参加できるか否かによって、パブリックチェーン、プライベートチェーンの2種類がある。
・パブリックチェーンはオープンで誰でも参加できるブロックチェーンで不正を働く者や正常に動作しない者も含まれる前提でシステムを運用する必要がある。そのためにはProof of Workのようなコンセンサスアルゴリズムを必要とし、合意形成に数十分の時間がかかる。
・プライベートチェーンでは参加のために管理者の承認を必要とすることで悪意を持つ参加者が含まれるリスクを抑えやすいことから、厳格なコンセンサスアルゴリズムがなくとも機能する。

(参考)
・【保存版】超わかりやすいブロックチェーンの基礎知識https://www.softbank.jp/biz/blog/business/articles/201804/blockchain-basic/

4.ブロックチェーンに関するキーワード
(1)分散ハッシュテーブル
 分散ハッシュテーブル( Distributed Hash Table, DHT)とは、ハッシュテーブルを複数のピアで管理する技術のこと。2001年に発表されたCAN、Chord、Pastry、Tapestryが代表的なアルゴリズムとして挙げられる。アドレスとコンテンツのハッシュ値を空間に写像し、その空間を複数のピアで分割管理することで、特定ピアに負荷が集中することなく大規模なコンテンツ探索を実現するオーバーレイ・ネットワーク。(参考:wikipedia)

(2)オーバーレイ・ネットワーク
 オーバーレイ・ネットワーク (overlay network) は、あるコンピュータネットワークの上に構築された別のコンピュータネットワークで、オーバーレイ・ネットワーク上のノードは下位ネットワークのトポロジーを意識せずに通信することができる。P2Pソフトウェアはオーバレイ・ネットワークを利用したもので、エンドホストにオーバレイプロトコルソフトウェアを搭載している。(参考:wikipedia)

(3)ハッシュテーブル
 ハッシュテーブル ( hash table) は、キーと値の組(エントリと呼ぶ)を複数個格納し、キーに対応する値をすばやく参照するためのデータ構造でハッシュ表ともいう。(参考:wikipedia)

(4)ハッシュ
 ハッシュ関数(hash function) (要約関数ともいう)は、任意のデータから、別の値を得るための関数のこと。ハッシュ関数から得られた値のことを要約値やハッシュ値またはハッシュという。ハッシュ関数の入力をキー (key)と呼び、得られるハッシュ値は、2つ以上のキーから同じ値が得られることがあり、これを衝突という。
 ハッシュ関数は用途によって、MD5(Message Digest Algorythm 5)、SHA-2(Secure Hash Algorighm2、シャーツー)、SHA-3(Secure Hash Algorighm3、シャースリー)などがある。
 SHA-2は、SHA-256(ハッシュ値:256bit)、SHA-512(ハッシュ値:512bit)などのバリエーションを総称したもの。

(5)コンセンサスアルゴリズム
 コンセンサスアルゴリズムはデータの真正性を担保するルールで、多くの利用者が持っているデータが正しいものかどうかを証明し担保する方法として、取引データを格納するブロックを「誰が作るか」を定義し、そのルールにもとづいて作られた1つのブロックを「正しいブロック」として認める、というルールのタイプを表すのがコンセンサスアルゴリズムです。
 主なコンセンサスアルゴリズムとして、PoW(プルーフ・オブ・ワーク)、PoS(プルーフ・オブ・ステーク、PoI(プルーフ・オブ・インポータンス)などがある。

・PoW(プルーフ・オブ・ワーク)
 ブロックを生成するの1つの「ナンス値」を探して膨大な試行錯誤を繰り返し、世界中のマイナー(採掘者)たちの競争で最も早く正解であるナンス値を見つけた人がブロック生成の権利を得るコンセンサスアルゴリム。

・PoS(プルーフ・オブ・ステーク)
 誰がブロックを生成するかはランダムに決定されるが通貨の保有量が多いほどブロックを生成できる確率が高まるコンセンサスアルゴリム。

・PoI(プルーフ・オブ・インポータンス)
 通貨の保有量が勘案されるPoSの発展型ともいえる方式で保有量に加えて取引回数や取引量など、いくつかの指標を設けてその通貨に対する保有者の「重要度」をスコアリングしてブロック生成者を決める方式。

5.ブロックチェーンプログラム
(1)実行環境
・バーチャルボックスcentos8
# cat /etc/redhat-release
CentOS Linux release 8.4.2105
・pyhton3のインストール

# dnf -y install python36

# pip3 –version
pip 9.0.3 from /usr/lib/python3.6/site-packages (python 3.6)
・pipenv.のインストール
# pip3 install pipenv
# pipenv install
# pip install Flask==0.12.2 requests==2.18.4

(2)ブロックチェーン
 ブロックチェーンのイメージを理解するため、ブロックのデータ(前回のハッシュ値を含む)からハッシュ値を求めて、前回のブロックに追加するイメージをプログラムで表現する。
 ブロックチェーンのイメージ図

block_sample1.py

import hashlib, json
import datetime

class Block:
    def __init__(self, index, timestamp, prev_hash, data):
        self.index = index #ブロック番号
        self.timestamp = timestamp #日付を記録
        self.prev_hash = prev_hash #一つ前のブロックのハッシュ値
        self.data = data #データ
        self.now_hash = self.calc_hash() #ハッシュ値の計算

    def calc_hash(self): #ハッシュ値の計算
       #now_hash(今回のブロック)を除いたデータをjsonに変換しsha256でハッシュ化
        block_data = {
            'index'       : self.index,
            'timestamp'   : self.timestamp,
            'prev_hash'   : self.prev_hash,
            'data' : self.data
        }
        json_text = json.dumps(block_data, sort_keys=True)
        return hashlib.sha256(json_text.encode('ascii')).hexdigest()
#ブロックの生成とブロックを繋げていくイメージ
block_chain = []
#最初のブロック
st_block = Block(0, str(datetime.datetime.now()), '-', "初回のデータ")
block_chain.append(st_block)
#最初のブロックから追加していく
for i in range(5):
        new_block = Block(i+1, str(datetime.datetime.now()), block_chain[i].now_hash, "データ"+str(i+1))
        block_chain.append(new_block)

#ブロックチェーンのデータを表示
#ブロック番号、ハッシュ値、前回のブロックのハッシュ値、ブロックデータ
for block in block_chain:
        print("index:",block.index,"\n","now_hash:",block.now_hash,"\n","prev_hash:",block.prev_hash,"\n","data:",block.data,"\n")

# python3 block_sample1.py

The end

YAMLの基本

1.YAMLとは
 YAML(YAML Ain’t Markup Language)はデータを構造化して表現するための記法を定めたデータ形式の一つで、 ソフトウェアの設定ファイルの記述やデータ交換などで使われる。
 YAMLはスカラー、シーケンス、マッピングといったデータ形式をインデントで表現することを基本とする。

2.YAMLの書き方
・スカラー
 YAMLでは数字や文字列、真偽値など基本的な値を表現できる

version:1.0
name: "fugafuga"
boolean: true

・シーケンス(配列・リスト)
 要素の集合をシーケンスで表現できる
 要素はインデント、ダッシュ(-)、スペースの後に続けて書く

list:
 - 1.0
 - fugafuga
 - true

・マッピング(ハッシュ、辞書)
 key:value型のコレクションをマッピングとして表現できる

map:
 name: "fugafuga"
 version: 1.0
 boolean: true

 シーケンスの中にマッピングをネストしたり、マッピングの中にシーケンスをネストしたりすることができる。

・シーケンスの中に要素をマッピングする 

YAML
list:
   - name: "fugafuga"
     version: 1.0
     boolean: true
   - name: "thomhom"
     version: 2.0
     boolean: true

JSONに変換
{
	"list": [
		{
			"name": "fugafuga",
			"version": 1,
			"boolean": true
		},
		{
			"name": "thomhom",
			"version": 2,
			"boolean": true
		}
	]
}

・マッピングの中にシーケンスを入れる

YAML
listMenu:
 list1:
   - name: "fugafuga"
     version: 1.0
     boolean: true
   - name: "thomhom"
     version: 2.0
     boolean: true

 list2:
   - name: "fu"
     version: 3.0
     boolean: true
   - name: "hom"
     version: 3.1
     boolean: true

JSONに変換
{
	"listMenu": {
		"list1": [
			{
				"name": "fugafuga",
				"version": 1,
				"boolean": true
			},
			{
				"name": "thomhom",
				"version": 2,
				"boolean": true
			}
		],
		"list2": [
			{
				"name": "fu",
				"version": 3,
				"boolean": true
			},
			{
				"name": "hom",
				"version": 3.1,
				"boolean": true
			}
		]
	}
}
YAML
employees:
  employee:
    - id: '1'
      firstName: Tom
    - id: '2'
      firstName: Maria
    - id: '3'
      firstName: James

JSONに変換
{
  "employees": {
    "employee": [
      {
        "id": "1",
        "firstName": "Tom"
      },
      {
        "id": "2",
        "firstName": "Maria"
      },
      {
        "id": "3",
        "firstName": "James"
      }
    ]
  }
}

(参考)YAMLコンバータで変換
 https://codebeautify.org/

The end

Linux sedコマンド

1.sedとは
 sedは”Stream EDitor”の略で、sedスクリプトコマンドファイル名で指定したファイルをコマンドに従って処理し、標準出力へ出力する。

2.動作環境
ここでの実行環境は次の通り。
・VirtualBox Ubuntu 16.04.7 LTS
・sedのバージョン
 $ sed –version
 sed (GNU sed) 4.2.2
 Copyright (C) 2012 Free Software Foundation, Inc.
 License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html.
 This is free software: you are free to change and redistribute it.
 There is NO WARRANTY, to the extent permitted by law.
 :

3.sedの基本
3.1 sedの基本構文
(1)sedコマンドの書式
 sed [オプション ・・・] ファイル名 [ファイル名2 ・・・]
sed [-v] [–version] [-h] [–help]
・sedの主なオプション
 -e スクリプト 処理内容を指定
  d 削除する
  s 指定したパターンに対して置換を行う
  g すべて置換する
  w 編集結果を別ファイルに保存する
  y 文字の置き換え・圧縮する
 -f ファイル名
  指定したスクリプトファイルからコマンドを読み込む
 -V, –version
  バージョン情報を表示
 -h, –help
  ヘルプ
 -E,-r 拡張正規表現を使う
 -i, 標準出力せずにファイルを上書き

3.2 sedコマンドの使い方
・テストで使うテキストデータ
 data.txt

1,apple
2,orange
3,Grape

(1)置換
・”apple”と 最初にマッチした箇所 を”APPLE”に置換
 $ sed -e “s/apple/APPLE/” data.txt
 1,APPLE
 2,orange
 3,Grape

・置換した結果をパイプでファイルに出力
 $ sed -e “s/apple/APPLE/” data.txt > data_new.txt
 $ vi data_new.txt 
 1,APPLE
 2,orange
 3,Grape
 ※この場合は処理部分を”(ダブルクォーテーション)で囲まなくても同じ結果が得られるが、”s/apple/A P P L E/”などスペースを使うときは”(ダブルクォーテーション)で囲まないと正しく処理されない。
(2)削除
・3行目を削除する
 $ sed -e 3d data.txt
 1,apple
 2,orange
(3)置換してファイル上書き
 $ sed -i s/orange/ORANGE/ data.txt
 $ vi data.txt
 1,apple
 2,ORANGE
 3,Grape

3.3 スクリプトファイルから読む
sample2.sed

s/orange/ORANGE/

$ sed -f sample2.sed data.txt
1,apple
2,ORANGE
3,Grape

3.4 スクリプトとして実行する
(1)引数無し 
 test1.sh

#! /bin/bash
sed -f sample2.sed data.txt

スクリプトファイルの実行権限を設定する
$ chmod +x test2.sh

  $ ./test1.sh
  1,apple
  2,ORANGE
  3,Grape
(2)ファイルを引数にする
  test2.sh

#! /bin/bash
FILE1=${1}
sed -f sample2.sed ${FILE1}

スクリプトファイルの実行権限を設定する
  $ chmod +x test2.sh
  $ ./test2.sh data.txt
  1,apple
  2,ORANGE
  3,Grape

3.5 C言語のプログラムからスクリプトファイルを実行
(1)引数無し
・data.txt

1,apple
2,orange
3,Grape

・test1.sh

#! /bin/bash
sed -f sample2.sed data.txt

・sed_test1.c

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    int ret=system("./test1.sh");
    printf("system()戻り値:%d\n",ret);
    return 0;
}

・sed_test1.cをコンパイルし、実行
 Linux の system 関数はプログラムの起動に成功すると0を返し、失敗すると-1を返す。
 $ gcc -o sed_test1 sed_test1.c
 $ ./sed_test1
 1,apple
 2,ORANGE
 3,Grape
 system()戻り値:0

(2)ファイルを引数にする
sed_test2.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
    char s1[]="./test2.sh ";
    strcat(s1,argv[1]); //文字列の結合
    int ret=system(s1);
    printf("system()戻り値:%d\n",ret);
    printf("argv[1]:%s\n",argv[1]);
    printf("s1:%s\n",s1);
    return 0;
}

 $ gcc -o sed_test2 sed_test2.c
 $ ./sed_test2 ./data.txt
 1,apple
 2,ORANGE
 3,Grape
 system()戻り値:0
 argv[1]:./data.txt
 s1:./test2.sh ./data.txt

The end

Linux awkコマンド

1.awkとは
 awk(オーク)はスクリプト・インタプリタで、空白などで区切られたテキストの処理、演算機能もあるプログラミング言語であるが、Linuxのコマンドのように扱うことができる。

2.動作環境
ここでの実行環境は次の通り。
・VirtualBox Ubuntu 16.04.7 LTS
・awkのバージョン
 $ awk -W version
 mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan
 compiled limits:
 max NF 32767
 sprintf buffer 2040

3.awkの基本
3.1 awkの基本構文
(1)awkコマンドの書式
 awk [オプション] [コマンド] [ファイルのパス]
 ・awkの主なオプション
 -f ファイル名 awkスクリプトが書かれたファイルを指定する
 -F 区切り文字 区切り文字を指定する(デフォルトは空白文字)
 -v 変数名=値 変数を定義する

 awkはテキストファイルをレコード(行)ごとに処理を行い、フィールド(列)に対する処理を記述する。フィールド(列)に関しては下記の組み込み変数で指定する。
 ・組み込み変数
  $1, $2, …, $n, … : 第n列目のデータ
  NF: フィールド(列)の数(1からスタート)
  NR: 行番号(1からスタート)

(2)awkコマンドの使い方
 コマンドはパターンとアクションに分けて、”awk ‘パターン {アクション}’ [ファイルのパス]”で、テキストファイルを1行ずつ読み、パターンに合致した行に対して、アクションで指定された内容を実行する。
 パターンを指定しないで”awk ‘{アクション}’ [ファイルのパス]”としたときは全ての行が処理の対象となる。

 (例)data.txtのファイルの内容を表示する
 data.txt

1 apple1
2 orange2
3 Grape3

・$0を使用することで全てのフィールド(列)を参照。
 $ awk ‘{print $0}’ ./data.txt
 1 apple
 2 orange
 3 Grape
・$1を使用することでフィールド1(列1)を参照。
 $ awk ‘{print $1}’ data.txt
 1
 2
 3
・$1 $2を使用することでフィールド1(列1)とフィールド2(列2)を参照。
 $ awk ‘{print $1 $2}’ ./data.txt
 1apple
 2orange
 3Grape
・$1と$2の間に文字を挿入
 $ awk ‘{print $1 “/” $2}’ ./data.txt
 1/apple
 2/orange
 3/Grape
・フィールド1(列1)とフィールド2(列2)を”,”で区切った場合(デフォルトはスペース区切り)-Fオプション
 data.txt

1,apple
2,orange
3,Grape

$ awk -F , ‘{print $1 $2}’ ./data.txt
 1apple
 2orange
 3Grape
・’コマンド’に「パターン」を含むとき
 awk ‘パターン { アクション }’ [ 入力ファイルのパス ]
 awk ‘$1==1 {print $1, $2}’ ./data.txt
 1 apple
(3)パターンの組み合わせ
 パターン1 && パターン2:パターン1とパターン2の両方に合致
 $ awk ‘$1==1 && $2==”apple” {print $1, $2}’ ./data.txt
 1 apple

 パターン1 || パターン2:パターン1またはパターン2に合致
 $ awk ‘$1==1 || $1==2 {print $1, $2}’ ./data.txt
 1 apple
 2 orange
(4)BEGIN(前処理)とEND(後処理)
テキストの処理を開始する前に実行したい処理がある場合は”BEGIN {アクション}”で指定し、最終行の処理の後の処理は”END {アクション}”で指定する。
 $ awk ‘BEGIN{ i=0 } {print ++i,$0 } END{ print i,” 行” }’ ./data.txt
 1 1 apple
 2 2 orange
 3 3 Grape
 3 行
(5)awk用のファイルで処理(-fオプション)
 (4)項のコマンドをファイルにする
  sample1.awk

BEGIN{
 i=0
}
{
print ++i,$0
}
END{
print i," 行"
}

実行
  $ awk -f sample1.awk ./data.txt
  1 1 apple
  2 2 orange
  3 3 Grape
  3 行
(6)スクリプトとして実行する
 (5)項で作成したawk用のファイルの1行目に”#! /usr/bin/awk -f”を書く

#! /usr/bin/awk -f
BEGIN{
 i=0
}
{
print ++i,$0
}
END{
print i," 行"
}

 スクリプトファイルの実行権限を設定する
 $ chmod +x sample1.awk
 $ ./sample1.awk ./data.txt
 1 1 apple
 2 2 orange
 3 3 Grape
 3 行

3.2 C言語のプログラムからawkスクリプトファイルを実行
・data.txt

1,apple
2,orange
3,Grape

・sample1.awk

#! /usr/bin/awk -f
BEGIN{
 i=0
}
{
print ++i,$0
}
END{
print i," 行"
}

・awk_test.c

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    int ret=system("./sample1.awk ./data.txt");
    printf("system()戻り値:%d\n",ret);
    return 0;
}

・awk_test.cをコンパイルし、実行
 Linux の system 関数はプログラムの起動に成功すると0を返し、失敗すると-1を返す。
 $ gcc -o awk_test awk_test.c
 $ ./awk_test
 1 1,apple
 2 2,orange
 3 3,Grape
 3 行
 system()戻り値:0

The end

PostgreSQL

1.PostgreSQLとは
PostgreSQLは、カリフォルニア大学バークレイ校のコンピュータサイエンス学科で開発されたPOSTGRES, Version 4.2をベースにしたオブジェクトリレーショナルデータベース管理システム(ORDBMS)。

2.PostgreSQLのインストールと基本

2.1 動作環境
 VirtualBox仮想マシン
 ホストOS Windows10 
 ゲストOS Ubuntu 16.04

2.2 PostgresSQLのインストール
https://www.postgresql.org/download/
(1)ファイルリポジトリ構成を作成
 $ sudo sh -c ‘echo “deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main” > /etc/apt/sources.list.d/pgdg.list’
(2)リポジトリ署名キーをインポート
 $ wget –quiet -O – https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add –
(3)パッケージリストを更新
 $ sudo apt-get update
(4)最新バージョンのPostgreSQLをインストール
 $ sudo apt-get -y install postgresql
(5)バージョン確認
 $ psql –version
 psql (PostgreSQL) 13.3 (Ubuntu 13.3-1.pgdg16.04+1)

2.3 PostgreSQLのロールとデータベースの使用
(1)postgresユーザにログインする
 ※postgresインストール時にOSのユーザpostgresが自動的に作成される
 $ sudo -i -u postgres
 postgres@****-VirtualBox:~$

pqsl --help
psql は PostgreSQL の対話型ターミナルです。
使い方:
  psql [オプション]... [データベース名 [ユーザ名]]

一般的なオプション:
  -c, --command=コマンド   単一の(SQLまたは内部)コマンドを一つだけ実行して終了
  -d, --dbname=DB名        接続するデータベース名(デフォルト: "koba")
  -f, --file=FILENAME      ファイルからコマンドを読み込んで実行後、終了
  -l(エル), --list         使用可能なデータベース一覧を表示して終了
  -v, --set=, --variable=名前=値
                           psql 変数 '名前' に '値' をセット
                           (例: -v ON_ERROR_STOP=1)
  -V, --version            バージョン情報を表示して終了
  -X, --no-psqlrc          初期化ファイル (~/.psqlrc) を読み込まない
  -1 (数字の1), --single-transaction
                           (対話形式でない場合)単一のトランザクションとして実行
  -?, --help[=options]     このヘルプを表示して終了
      --help=commands      バックスラッシュコマンドの一覧を表示して終了
      --help=variables     特殊変数の一覧を表示して終了

入出力オプション:
  -a, --echo-all           スクリプトから読み込んだ入力をすべて表示
  -b, --echo-errors        失敗したコマンドを表示
  -e, --echo-queries       サーバへ送信したコマンドを表示
  -E, --echo-hidden        内部コマンドが生成した問い合わせを表示
  -L, --log-file=FILENAME  セッションログをファイルに書き込む
  -n, --no-readline        拡張コマンドライン編集機能(readline)を無効にする
  -o, --output=FILENAME    問い合わせの結果をファイル (または |パイプ)に送る
  -q, --quiet              静かに実行 (メッセージなしで、問い合わせの出力のみ)
  -s, --single-step        シングルステップモード (各問い合わせごとに確認)
  -S, --single-line        単一行モード (行末でSQLコマンドを終端)

出力フォーマットのオプション
  -A, --no-align           桁揃えなしのテーブル出力モード
      --csv                CSV(カンマ区切り)テーブル出力モード
  -F, --field-separator=文字列
                           桁揃えなし出力時のフィールド区切り文字
                           (デフォルト: "|")
  -H, --html               HTML テーブル出力モード
  -P, --pset=変数[=値]     表示オプション '変数' を '値' にセット
                           (\pset コマンドを参照)
  -R, --record-separator=文字列
                           桁揃えなし出力におけるレコード区切り文字
                           (デフォルト: 改行)
  -t, --tuples-only        行のみを表示
  -T, --table-attr=TEXT    HTMLテーブルのタグ属性をセット (width, border等)
  -x, --expanded           拡張テーブル出力に切り替える
  -z, --field-separator-zero
                           桁揃えなし出力のフィールド区切りをバイト値の0に設定
  -0, --record-separator-zero
                           桁揃えなし出力のレコード区切りをバイト値の0に設定

接続オプション:
  -h, --host=HOSTNAME      データベースサーバのホストまたはソケットの
                           ディレクトリ(デフォルト: "/var/run/postgresql")
  -p, --port=PORT          データベースサーバのポート番号(デフォルト: "5432")
  -U, --username=USERNAME  データベースのユーザ名 (デフォルト: "***")
  -w, --no-password        パスワード入力を要求しない
  -W, --password           パスワードプロンプトの強制表示(本来は自動的に表示)

詳細はpsqlの中で"\?"(内部コマンドの場合)または"\help"(SQLコマンドの場合)
をタイプするか、またはPostgreSQLドキュメント中のpsqlのセクションを参照のこと。

バグは<pgsql-bugs@lists.postgresql.org>に報告してください。
PostgreSQL ホームページ: <https://www.postgresql.org/>

(2)データベース一覧の表示
 $ psql -l

(3)データベースの削除
 dropdb <データベース名>
(4)新しいデータベースを作成
 createdb <データベース名>
 $ createdb mydb

(5)データベースに接続
 psql -d <データベース名>
(例)
 $ psql -d mydb
 mydb=#
(6)テーブルの作成

mydb=# CREATE TABLE weather (
    city            varchar(80),

    temp_lo         int,           -- 最低気温
    temp_hi         int,           -- 最高気温
    prcp            real,          -- 降水量
    date            date
);

(7)テーブルリスト表示
 postgres=# SELECT * FROM weather;

(8)テーブル一覧の表示
 mydb=# \dt

(9)テーブルのスキーマの詳細表示
 mydb=# \d <テーブル名>

(10)テーブルのレコード追加
 mydb=# INSERT INTO weather VALUES (‘japan tokyo’, 32, 38, 0.50, ‘1998-12-10’);

(11)テーブルのレコード検索
 mydb=# SELECT * FROM weather;
 mydb=# SELECT * FROM weather WHERE city=’japan oosaka’;

(12)テーブルのアクセス権限の表示
 mydb=# \z <テーブル名>

(13)テーブルの削除
 mydb=# drop table <テーブル名>;

(14)PostgreSQLプロンプトの終了
 mydb=# \q

3.PostgresSQLのロールについて
 ロールは操作権限などの役割を示すものでPostgresSQLではユーザ管理はロールで行う。OS上のユーザーとは別に扱われ、OS上のユーザーとロールとの対応は、「pg_hba.conf」ファイルで設定されている。

(1)スーパーユーザpostgresでpsqlを起動して、postgresのDBにログインする
 $ psql -U postgres -d postgres
(2)ロール(user01)を作成する
 postgres=# CREATE ROLE user01;
(3)ログイン権限を与える
 postgres=# ALTER ROLE user01 LOGIN; 
(4)パスワードを設定する
 postgres=# ALTER ROLE user01 PASSWORD ‘1212’;
(5)ロールuser01でデータベースにアクセスする
 postgres@*-VirtualBox:~$ psql -U user01 -d postgres
 psql: エラー: FATAL: ユーザ”user01″で対向(peer)認証に失敗しました
※peer認証とは
 PostgreSQL内のユーザーとUNIXユーザで、ユーザー名が一致していれば認証情報なしでログインできる仕組みで、psql側でユーザーを作るときには同名のUNIXユーザーも追加する必要がある。ここでは、テスト用として認証方法を変更して進める。
pg_hba.confファイル
PostgreSQLに接続するクライアントの認証に関する設定を記述するファイル
$ cd /etc/postgresql/13/main
$ ls -al

/etc/postgresql/13/main# vi pg_hba.conf

(変更前)
# Database administrative login by Unix domain socket
local   all             postgres                                peer
# "local" is for Unix domain socket connections only
local   all             all                                     peer

※認証方式
trust:任意のロール名でパスワードなしで接続可能
md5:パスワード認証
peer:Peer認証
peerをtrustに変更

(変更後)
# Database administrative login by Unix domain socket
local   all             postgres                                trust
# "local" is for Unix domain socket connections only
local   all             all                                     trust

(6)user01でpostgresに接続する
 psql -h ホスト名 -p ポート番号 -U ロール名 -d データベース名
 $ psql -h localhost -p 5432 -U user01 -d postgres
 パスワードは前述で設定した’1212′

ホスト名:ローカルホストで動いている PostgreSQL に接続する場合は省略可
ポート番号:デフォルトの値(通常は 5432 )で別の番号を使用するとき以外は省略可
ロール名:省略した場合は OS のユーザー名が使用される

(7)ロール一覧
 =# \du

(8)コマンドプロンプト
 =# スーパーユーザpostgresからデータベースに接続したとき
 => スーパーユーザ以外からデータベースに接続したとき

# psql -U user01 -d mydb
 psql (13.3 (Ubuntu 13.3-1.pgdg16.04+1))
 "help"でヘルプを表示します。
 mydb=>

 # psql -U postgres -d mydb
 psql (13.3 (Ubuntu 13.3-1.pgdg16.04+1))
 "help"でヘルプを表示します。
 mydb=#

(9)SQLコマンドの分割入力
 SQLコマンドを実行するときは最後にセミコロン”;”を入力してから、[Enter]キーを押します。セミコロンが入力される前に[Enter]キーを押した場合は入力が分割されたものとして扱われ、コマンドプロンプトが”=#”(”=>”)から”-#”(”->”)に変わります。

4.PostgresSQLのスキーマについて
 スキーマとは、1つのデータベースの中に複数設定することができる名前空間で自由に定義できる。
(1)スキーマ作成
mydb=# create schema <スキーマ名>
(2)スキーマの確認
 mydb=# select current_schema;
(3)スキーマの一覧
 mydb=# \dn

(4)スキーマの変更
 mydb=# set search_path to <schema_name>;

5.PostgreSQLアンインストール
(1)パッケージリストの確認
 postgresqlのパッケージリストを確認
 $ dpkg -l | grep postgres

(2)Postgresパッケージの削除
 $ sudo apt remove –purge postgresql
 $ sudo apt remove –purge postgresql-13
 $ sudo apt remove –purge postgresql-client-13
 $ sudo apt remove –purge postgresql-client-common
 $ sudo apt remove –purge apostgresql-common
 すべて、y、または「はい」で続ける
(3)再起動
 $ shutdown -r now
(4)postgresユーザの削除
 $ sudo userdel postgres

 The end

述語論理とPrologプログラミング

1.この記事で使用する論理記号
・→ 含む(A→B、A⊃B)
・⇔ 同値(A≡B、A⇔Bは、AとBがともに真、又は偽のときのみ真)
・¬ 否定(!、~)
・⋀ 論理積(&、・)
・⋁ 論理和(+)
・∀ 全ての、任意の(全称量化)
・∃ 存在する(存在量化)
・∃! 唯一存在量化(ただ1つ存在する)
・:= 定義(x := y は、x を yの別名として定義)

2.述語論理
 命題論理では命題が真か偽かについてのみ考え、命題が表している対象については考えない。命題論理は最小単位である「要素命題」(真偽が問える最小の文)から成る。
 「全ての人間は死ぬ」は要素命題(”全ての人間”と”死ぬ”を分けると真偽が問えない)である。
 そこで次の推論を考える
 (前提)全ての人間は死ぬ
 (前提)ソクラテスは人間である
 (結論)ソクラテスは死ぬ
 この推論を命題論理で表現すると、
  p:=「全ての人間は死ぬ」
  q:=「ソクラテスは人間である」
  r:=「ソクラテスは死ぬ」
  p,q→r
 となり、要素命題を記号化したことでrはp,qに無関係な記号となり、この推論式では真偽はわからない。
 そこで、命題論理の拡張である述語論理を使って、要素命題を「もの」の性質やそれらの関係を表わすように拡張する。
 ここで、
 ソクラテス:固有名(個体定項)を記号化する(小文字a)
 人間 :不特定の個体(個体変項)を記号化する(小文字x)
 述語:個体の性質や関係を表わす表現を述語と呼び、大文字の記号で表わす。
 「全ての人間は死ぬ」では「~は死ぬ」が述語となり、
 Q(x):=「~は死ぬ」で表わす。
 「ソクラテスは人間である」では「~は人間である」が述語となり、  
 P(x):=「~は人間である」で表わす。
 述語論理では、個体変項に「すべて」や「ある」といった量を与えることを「量化する」といい、∀(全称記号で「すべての~」)と∃(存在記号で「ある~」)を使う。
 従って、前記の命題論理を述語論理で表わすと、
 P(ソクラテス):=「ソクラテスは人間である」
 ∀x(P(x)→Q(x)):=「全て人間について、人間は死ぬ」
 Q(ソクラテス):=「ソクラテスは死ぬ」
 となる。

3.述語論理のPrologプログラム
3.1 Prologとは
 記号処理を目的につくられた非数値計算用プログラミング言語で、一階述語論理(述語論理の中でも固体の量化のみを許すもの)プログラムは複数の節と呼ばれる構造からなる。プログラムの流れは、事実や規則の集合に対して質問をし、その質問にあてはまるものを Prolog が自動で返すように動作する。
 また、Prologは論理型プログラミング言語で、1982年の第五世代コンピュータ計画では述語論理を基礎にした自動推論を高速実行する並列推論マシンの開発の目標が掲げられ、並行論理プログラムの土台としてPrologが採用され10年の歳月をPrologと並行論理の研究に費やしたが一般市場での応用には至らなかったとのこと。現在では、Prolog は各教育機関で主に論理学の教材として利用されている。

 Prologのプログラムは次の3つの要素から成る。
 ①事実: 事物とその関係についていくつかの事実を宣言すること。
 述語(対象 1, 対象 2,···, 対象 n)
 「”対象 1”,”対象 2”,···,”対象 n” は”述語”である」を表わす
 規則: 事物とその関係についての規則を定義すること。
 ②帰結 :- 条件
 「”条件”を満たす場合,”帰結”は正しい」という規則を表わす
 P ⇒ Q(P ならばQ)という推論規則は,Q : −P と記述する
 ③質問: 事物とその関係について質問すること。

3.2 Prologのインストール
・動作環境
 Ubuntuバージョン
 $ cat /etc/os-release
 VERSION=”16.04.7 LTS (Xenial Xerus)”
・swi-Prologのインストール
 $ sudo apt install swi-prolog

3.3 サンプルプログラム
(例1)事実と規則を宣言
 P(ソクラテス):=「ソクラテスは人間である」
∀x(P(x)→Q(x)):=「全て人間について、人間は死ぬ」
 Q(ソクラテス):=「ソクラテスは死ぬ」
 Prolog 処理系では,アルファベット大文字で始まる語は変数として扱われる。

 test.pl

human(socrates).
mortal(A) :- human(A).
~/Prolog$ swipl test.pl
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.2.3)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).

?- mortal(socrates).
true.

(例2)事実を宣言
 likes.pl

likes(taro,hanako).
likes(taro,flower).
likes(jiro,hanako).
$ swipl likes.pl
?- likes(taro,X).
X = hanako ;
X = flower.

(例2)再帰処理
 nの階乗を求める 
 n!=n・(n−1)・(n−2)・・・2・1
 0!=1 
 
 fact.pl

fact(0, 1).                  
fact(N, F) :-
    N > 0,                   
    N1 is N - 1,             
    fact(N1, F1),            
    F is N * F1.             
$ swipl fact.pl
?- fact(3,X).
X = 6 .

・プログラムの終了
 ?- halt.

・トレースモード
 ?- trace. トレース開始
  creep  1ステップずつ実行
  skip  現在実行中の呼び出しのサブゴールに関する情報の表示をスキップ
  help  コマンドのヘルプを表示
  abort トレースを途中で中止し、プロンプト
・トレースモードの停止
 [trace] ?- nodebug.

?- trace.
[trace]  ?- fact(3,X).
   Call: (7) fact(3, _G1123) ? creep
   Call: (8) 3>0 ? creep
   Exit: (8) 3>0 ? creep
   Call: (8) _G1201 is 3+ -1 ? creep
   Exit: (8) 2 is 3+ -1 ? creep
   Call: (8) fact(2, _G1202) ? creep
   Call: (9) 2>0 ? creep
   Exit: (9) 2>0 ? creep
   Call: (9) _G1204 is 2+ -1 ? creep
   Exit: (9) 1 is 2+ -1 ? creep
   Call: (9) fact(1, _G1205) ? creep
   Call: (10) 1>0 ? creep
   Exit: (10) 1>0 ? creep
   Call: (10) _G1207 is 1+ -1 ? creep
   Exit: (10) 0 is 1+ -1 ? creep
   Call: (10) fact(0, _G1208) ? creep
   Exit: (10) fact(0, 1) ? creep
   Call: (10) _G1210 is 1*1 ? creep
   Exit: (10) 1 is 1*1 ? creep
   Exit: (9) fact(1, 1) ? creep
   Call: (9) _G1213 is 2*1 ? creep
   Exit: (9) 2 is 2*1 ? creep
   Exit: (8) fact(2, 2) ? creep
   Call: (8) _G1123 is 3*2 ? creep
   Exit: (8) 6 is 3*2 ? creep
   Exit: (7) fact(3, 6) ? creep
X = 6

[trace]  ?- nodebug.
?-

The end

SSH接続について

目次

1.SSH接続とは
 SSH(Secure Shell)は遠隔でコンピューター機器を操作するときに通信データを暗号化するプロトコルである。また、通信データを暗号化する意味では同じあるSSL(Secure Socket Layer)はインターネット上での端末とサーバ間の通信データを暗号化するプロトコルである。
 SSHでは認証方式として、公開鍵認証方式(「公開鍵」と「秘密鍵」を照合して認証する方法)が使われ、SSLではサーバ証明書、又はクライアント証明書による認証方法が使われ、用途が異なる。ここではSSH接続について扱う。

2.SSHの認証方式
(1)公開鍵認証方式
 秘密鍵(データに電子署名を行うもの)と公開鍵(電子署名されたデータが正しいか検証できるもの)の2つの鍵(キーペア)を使って認証する方法である。秘密鍵を持っている人(パソコン)からのみログインを許可することができる。

(2)パスワード認証方式
 サーバ側にユーザー名とパスワードのアカウント情報を設定しておき、パソコンから一致するパスワードが入力されたときログインできるようするもの。

3.SSHクライアントソフト
・OpenSSH
 OpenSSH (OpenBSD Secure Shell) とは、SSHプロトコルを利用するためのソフトウェアで、SSHサーバおよびSSHクライアントの両方の機能を含む。OpenBSDプロジェクトにより開発が行われ、BSDライセンスで公開されている。
 https://www.openssh.com/

・Putty
 Simon TathamがMIT Licenceで開発·公開しているリモートログオンクライアント。
 対応している通信プロトコルはSSH、Telnetやrloginなどがある。また、PuTTYを複数起動して複数の端末に同時に接続することができる。

・Teraterm
 Tera Termは、Windowsプラットフォームで動作するリモートログオンクライアント。
 対応している通信プロトコルはSSH、Telnet、シリアルなどある。

4.サーバにSSHで公開鍵認証方式によりログイン

4.1 実行環境
・Windows10にVirtualBoxの仮想マシンがインストールされている
・仮想マシンのOSはCentOS8

4.2 サーバにユーザ・パスワードでログインする

4.3 公開鍵と秘密鍵を作成する
 $ ssh-keygen -t rsa
 入力は全て、空欄としてEnter

4.4 作成されたキー、ディレクトリのパーミッション

4.5 公開鍵ファイルのリネーム
 公開鍵のファイル名はsshd_configファイルでデフォルトで「authorized_keys」となっているため、公開鍵ファイル名をこれに合わせる。
(設定ファイル:/etc/ssh/sshd_config)

# mv id_rsa.pub authorized_keys

4.6 秘密鍵をPCへ転送する
ファイル>「SSH SCP…」を選択

 From:作成された秘密鍵ファイルを指定
 To:PCの転送先ディレクトリを指定
 「Receive」をクリックすると転送開始

4.7 Teratermでサーバに接続

4.6項の転送先ディレクトリの秘密鍵を指定して「OK」をクリックする。

4.8 Windows10のコマンドプロンプトからサーバに接続
 >ssh (user name)@127.0.0.1 -p 2222

The end

Httpsサーバとクライアントの作成

1.実行環境
・Windows10にVirtualBoxの仮想マシンがインストールされている
・仮想マシンのOSはCentOS8で、Apatch(HTTPサーバ)がインストールされている
(1)HTTPサーバのバージョンの確認
# httpd -v

(2)httpサーバの起動
# systemctl start httpd
# systemctl is-active httpd

(3)ブラウザから接続
/var/www/html
のフォルダにあるindex.html
が表示される

2.HttpサーバのSSL化
(1)SSLモジュールのインストール
ApacheでSSLを利用ため必要なソフトウェア
・OpenSSL:SSLを利用するために必要なソフトウェア
・mod_ssl:OpenSSLを使ってApacheをSSLに対応させるモジュール
OpenSSLはCentOSをデフォルト設定でインストールされる。OpenSSLがインストールされているかどうか確認する。
# rpm -qa | grep openssl

インストールされていないときは、下記のコマンドでインストールする。
# yum install openssl
バージョンの確認
# openssl version

CentOS8が2021年末にサポート切れでミラーサイトが停止され、パッケージのインストールに失敗した。

(対策)
 下記のファイルで、参照先のリポジトリをミラーサイトからhttp://vault.centos.orgに変更する。
/etc/yum.repos.d/CentOS*repo
①CentOS-Linux-AppStream.repo
②CentOS-Linux-BaseOS.repo

変更前:
[appstream]
name=CentOS Linux $releasever – AppStream
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=AppStream&infra=$infra
#baseurl=http://mirror.centos.org/$contentdir/$releasever/AppStream/$basearch/os/


mirrorlist=・・・をコメント化し、#baseurl=http://mirror.centos.org/・・・のコメントを外し、”mirror”を”vault”に変更
変更後:
[appstream]
name=CentOS Linux $releasever – AppStream
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=AppStream&infra=$infra
baseurl=http://vault.centos.org/$contentdir/$releasever/AppStream/$basearch/os/
参照先のリポジトリを変更したあと再度、下記コマンドでインストールする
# yum install mod_ssl

下記コマンドでインストールされたことを確認する
# rpm -qa | grep mod_ssl

※rpmコマンド
オプション-q:問い合わせ(パッケージ情報の表示と検索)
   -a:情報問い合わせ関連(-q、-Vと一緒に使用するオプション)でall

(4)秘密鍵とサーバ証明書の作成
 ・秘密鍵の作成
 # openssl genrsa > server.key

・サーバ証明書の作成
CSRファイル(認証局にサーバ証明書を発行してもらう時に使用するファイル)を作成
# openssl req -new -key server.key > server.csr
下記はEnterでテストでは入力無しとした

Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server’s hostname) []:
Email Address []:
Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
・サーバ証明書への署名
 本来はこのCSRファイルを認証局に渡して署名してもらう必要があるが、ここではテストのため、自分で署名するため、以下のコマンドを実行。
# openssl x509 -req -signkey server.key < server.csr > server.crt

(5)秘密鍵とサーバ証明書の配置
作成した鍵と証明書を/etc/httpd/以下に配置する。

ここでは
 /etc/httpd/conf/ssl.keyおよび/etc/httpd/conf/ssl.crt配下に置く
# mkdir /etc/httpd/conf/ssl.key
# mkdir /etc/httpd/conf/ssl.crt
# mv server.key /etc/httpd/conf/ssl.key/
# mv server.crt /etc/httpd/conf/ssl.crt/

(6)SSLモジュールの設定
/etc/httpd/conf.d/ssl.confの中に、配置した鍵と証明書のパスを設定する。
# vi /etc/httpd/conf.d/ssl.conf

#SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateFile /etc/httpd/conf/ssl.crt/server.crt

#SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
SSLCertificateKeyFile /etc/httpd/conf/ssl.key/server.key

(7)Apacheを再起動して接続する
# systemctl restart httpd
# systemctl is-active httpd
ssl.confを修正したあと、起動に失敗する

SELinuxが影響していると考えられるため、テストではSELinuxを無効とする
現在
[root@localhost conf.d]#  getenforce
Enforcing
一時的にpermissiveモードに変更
[root@localhost conf.d]#  getenforce
Permissive
上記の変更をしてhttpサーバが起動できた
[root@localhost conf.d]# systemctl restart httpd
[root@localhost conf.d]# systemctl is-active httpd
active

(8)ブラウザからHttpsサーバに接続
 CentOSのディスクトップのブラウザから接続
https://localhost

サーバから取得したサーバ証明書では、ルート証明書との正当性が確認できないため、エラーになったと考えられる。
「詳細情報」を選択して、次に進み、強制的に許可する。

また、ホストPC(Windows10)のブラウザからアクセスしたとき
http://localhostでは接続できるが、https://localhostでは接続できない

コマンドプロンプトからcurlコマンドで、SSL接続で証明書エラーをスキップして接続することで、httpsサーバからのレスポンスが正常に処理される。
# curl -k https://localhost

3.Httpsクライアントの作成
(1)openssl-devel パッケージのインストール
 openssl-devel は各種の暗号化アルゴリズムとプロトコルをサポートしたアプリケーションを開発するために必要な静的ライブラリとヘッダーファイルが含まれている。
# yum install openssl-devel

(2)クライアントのソースファイル
client.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <openssl/ssl.h>
#include <openssl/err.h>

int main(void) {
    int mysocket;
    struct sockaddr_in server;// ホストのIPアドレスなど情報を保持する構造体
    struct addrinfo hints, *res;

    SSL *ssl;
    SSL_CTX *ctx;

    char msg[100];

    char *host = "localhost";
    char *path = "/";
    int   port = 443;

    // IPアドレスの解決
    memset(&hints, 0, sizeof(hints));
    hints.ai_family   = AF_INET;//インターネットプロトコル
    hints.ai_socktype = SOCK_STREAM;
    char *service = "https";

    int err = 0;
    if ((err = getaddrinfo(host, service, &hints, &res)) != 0) {
        fprintf(stderr, "Fail to resolve ip address - %d\n", err);
        return EXIT_FAILURE;
    }

 //ソケット
    if ((mysocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) {
        fprintf(stderr, "Fail to create a socket.\n");
        return EXIT_FAILURE;
    }

  //コネクト
    if (connect(mysocket, res->ai_addr, res->ai_addrlen) != 0) {
        printf("Connection error.\n");
        return EXIT_FAILURE;
    }

 //SSLセットアップ
    SSL_load_error_strings();/OpenSSLのエラー文の読み込み

    SSL_library_init();//SSLの初期化

 //SSL_CTX構造体生成
    ctx = SSL_CTX_new(SSLv23_client_method()); //引数は使用するプロトコルの種類

//SSLの構造体生成
    ssl = SSL_new(ctx);
    err = SSL_set_fd(ssl, mysocket);//SSL構造体とソケットの関連付け
    SSL_connect(ssl);/サーバとハンドシェイクを行う
    printf("Conntect to %s\n", host);

 //HTTPリクエストの送信
    sprintf(msg, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n", path, host);

    SSL_write(ssl, msg, strlen(msg));

    int buf_size = 256;
    char buf[buf_size];
    int read_size;
//レスポンスの受信
    do {
        read_size = SSL_read(ssl, buf, buf_size);
        write(1, buf, read_size);
    } while(read_size > 0);
//SSLとソケットの終了処理
    SSL_shutdown(ssl);
    SSL_free(ssl);
    SSL_CTX_free(ctx);
    ERR_free_strings();

    close(mysocket);

    return EXIT_SUCCESS;
}

(3)クライアントソースファイルのコンパイル
 # gcc client.c -o client -lssl -lcrypto

(4)httpsサーバの起動
 # setenforce 0
 # systemctl start httpd

(5)httpsクライアントの起動
 # ./client

Conntect to localhost
HTTP/1.1 200 OK
Date: Sun, 22 May 2022 00:50:46 GMT
Server: Apache/2.4.37 (centos) OpenSSL/1.1.1k
Last-Modified: Sun, 08 May 2022 01:59:00 GMT
ETag: "c3-5de766f65c100"
Accept-Ranges: bytes
Content-Length: 195
Connection: close
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>画像テスト</title>
  </head>
  <body>
    <p>画像のテスト</p>
    <img src="test.jpg">
  </body>
</html>

httpサーバにsslで接続できて、レスポンスのhtmlファイルが返却された

The end