2019年10月31日木曜日

Python ローマ字 カナ変換

#!/usr/bin/env python36
# coding=utf-8
import json
import requests

def main():
  import io, sys
  import getopt
  from   pykakasi import kakasi
  import mojimoji


  usage =""" usage: ./kakasi.py [options]
  --help            本メッセージ
  --zipcode         郵便番号"""

  try:
    opts, args = getopt.getopt( sys.argv[1:], '-h', ['help','zipcode='])
  except getopt.GetoptError as err:
    print( str(err))
    print( usage )
    sys.exit()

  opt = dict( opts )

  if( '-h' in opt or len(opt)>1 ):
    print( usage )
    sys.exit()
  elif( '--zipcode' in opt ):
    zip= opt['--zipcode']
  else:
    zip = '1510061'

  print( 'REQUEST: ' +  zip)

  resp = requests.get( 'http://zipcloud.ibsnet.co.jp/api/search?zipcode=' + str(zip) + '&limit=1')

  response = json.loads(resp.text)
  address = response["results"][0]

  address1 = address["address1"]
  address2 = address["address2"]
  address3 = address["address3"]
  kana1    = address["kana1"]
  kana2    = address["kana2"]
  kana3    = address["kana3"]
  zipcode  = address["zipcode"]

  print( '---------取得データ---------')
  print( address1 )
  print( address2 )
  print( address3 )
  print( kana1 )
  print( kana2 )
  print( kana3 )
  print( zipcode )


  kakasi = kakasi()  # Generate kakasi instance

  print( '---------ローマ字変換--------')

  kakasi.setMode("H", "a")  # Hiragana to ascii
  kakasi.setMode("K", "a")  # Katakana to ascii
  kakasi.setMode("J", "a")  # Japanese(kanji) to ascii

  kakasi.setMode("r", "Hepburn")  # Use Hepburn romanization

  conv = kakasi.getConverter()
  roma_address1  = conv.do( address1 )
  roma_address2  = conv.do( address2 )
  roma_address3  = conv.do( address3 )
  roma_kana1     = conv.do( kana1 )
  roma_kana2     = conv.do( kana2 )
  roma_kana3     = conv.do( kana3 )
  roma_zipcode   = conv.do( zipcode )
  print( roma_address1 )
  print( roma_address2 )
  print( roma_address3 )
  print( roma_kana1 )
  print( roma_kana2 )
  print( roma_kana3 )
  print( roma_zipcode )

  print( '----------カナ変換---------')
  kakasi.setMode("H", "K")  # Hiragana to KANA
  kakasi.setMode("J", "K")  # Japanese(kanji) to KANA
  kakasi.setMode("a", "K")  # Japanese(kanji) to KANA

  conv = kakasi.getConverter()
  kana_address1  = conv.do( address1 )
  kana_address2  = conv.do( address2 )
  kana_address3  = conv.do( address3 )
  kana_kana1     = conv.do( kana1 )
  kana_kana2     = conv.do( kana2 )
  kana_kana3     = conv.do( kana3 )
  kana_zipcode   = conv.do( zipcode )
  print( kana_address1 )
  print( kana_address2 )
  print( kana_address3 )
  print( kana_kana1 )
  print( kana_kana2 )
  print( kana_kana3 )
  print( kana_zipcode )

  print( '--------全角変換------------')
  print( mojimoji.han_to_zen( kana_kana1) )
  print( mojimoji.han_to_zen( kana_kana2) )
  print( mojimoji.han_to_zen( kana_kana3) )

  print( '--------全角→ローマ字変換------------')

  kakasi.setMode("H", "a")  # Hiragana to ascii
  kakasi.setMode("K", "a")  # Katakana to ascii
  kakasi.setMode("J", "a")  # Japanese(kanji) to ascii

  kakasi.setMode("r", "Hepburn")  # Use Hepburn romanization
  print( conv.do( mojimoji.han_to_zen( kana_kana1) ))
  print( conv.do( mojimoji.han_to_zen( kana_kana2) ))
  print( conv.do( mojimoji.han_to_zen( kana_kana3) ))

if __name__ == "__main__":
    main()

2019年10月18日金曜日

wsgi 動かない。 503 Service Unavailable

Permission denied: [client 127.0.0.1:33562] mod_wsgi (pid=5683): Unable to connect to WSGI daemon process 'analyze' on '/etc/httpd/logs/wsgi.5655.0.2.sock' as user with uid=48.



# vi /etc/httpd/conf.d/wsgi.conf

WSGISocketPrefix run/wsgi
又は、
WSGISocketPrefix /var/run/wsgi

2019年10月10日木曜日

Django クラウドAPI REST認証

1.全体ツリー構造

1-1 ファルダ
TTG_Project
├── README
├── client                      # クライアントテストツール
│   ├── __pycache__
│   ├── client.py
│   ├── data.py                 # テストデータ
│   └── run                     # クライアント起動 ($ ./run)
└── server                      # Django サーバアプリケーション
    ├── api                     # API ファルダー
    │   ├── __init__.py
    │   ├── __pycache__
    │   ├── admin.py
    │   ├── apps.py
    │   ├── migrations
    │   ├── models.py
    │   ├── registerAPI.py      # レジスタ用web API
    │   ├── tests.py
    │   ├── urls.py
    │   └── views.py
    ├── build                   # マイグレション/起動スクリプト
    ├── clean                   # キャシュクリヤー
    ├── conf
    │   ├── __init__.py
    │   ├── __pycache__
    │   ├── settings.py         # DB設定等、各種設定
    │   ├── urls.py
    │   └── wsgi.py             # apache 起動入り口
    ├── env
    └── manage.py               # 手動起動入り口


2.環境構築
2-1 pythonのインストール
2-2 Djangoのインストール
2-3 プロジェクトの作成

$ mkdir TTG_Project
$ cd TTG_Project
$ django-admin startproject conf
$ mv conf server
$ cd server
$ python36 manage.py startapp api

2-4 settings.pyの編集

$ vi ./conf/settings.py

LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'

INSTALLED_APPS = [
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
  'api.apps.ApiConfig',             # 追記
  'rest_framework',                 # 追記
]

# 下記追記

from datetime import datetime, timedelta

REST_FRAMEWORK = {
  'DEFAULT_PERMISSION_CLASSES': (
  ¦ 'rest_framework.permissions.IsAuthenticated',
  ),
  'DEFAULT_AUTHENTICATION_CLASSES': (
  ¦ 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
  ),
  'NON_FIELD_ERRORS_KEY': 'detail',
  'TEST_REQUEST_DEFAULT_FORMAT': 'json'
}

JWT_AUTH = {
  'JWT_SECRET_KEY': SECRET_KEY,
  'JWT_ALGORITHM': 'HS256',
  'JWT_ALLOW_REFRESH': True,
  'JWT_EXPIRATION_DELTA': timedelta(days=7),
  'JWT_REFRESH_EXPIRATION_DELTA': timedelta(days=28),
}

# 下記ファイル作成を新規に作成
$ vi api/urls.py
from django.urls import path
from . import views
from rest_framework_jwt.views import obtain_jwt_token, verify_jwt_token, refresh_jwt_token

app_name = 'api'

urlpatterns = [
    path('token/', obtain_jwt_token),
    path('token/verify/', verify_jwt_token),
    path('token/refresh/', refresh_jwt_token),
    path('v1/register/', views.RegisterAPI.as_view()),
    path('v1/cxdnext/',  views.CxdnextAPI.as_view()),
]

2-5 conf/urls.pyの編集

$ vi conf/urls.py

from django.urls import include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('api.urls',   namespace='api')),    # 追記
]


3 デーベース

3-1 mysqlデータベース設定

$ vi conf/settings.py

import pymysql
pymysql.install_as_MySQLdb()

DATABASES = {
   'default': {
      'ENGINE': 'django.db.backends.mysql',
      'NAME': 'ttg',       # 予め空DBを作成しておく。
      'USER': 'admin',
      'PASSWORD':'password',
      'HOST': '',
      'PORT': '',
      'OPTIONS': {
            'charset': 'utf8mb4',
      },
      'ATOMIC_REQUESTS': True,
   },
   'db_ttg': {
      'ENGINE': 'django.db.backends.mysql',
      'NAME': 'ttg_data',   # 予め空DBを作成しておく。
      'USER': 'admin',
      'PASSWORD':'password',
      'HOST': '',
      'PORT': '',
      'OPTIONS': {
            'charset': 'utf8mb4',
      },
      'ATOMIC_REQUESTS': False,
   }
}

※  mysqlデータベースのインストール方法は省略します。

3-2 データベース構造
drop database ttg_data;
create database ttg_data;
use ttg_data;

create table  ttg_cart(
invoice        varchar(6)  not null comment "伝票コード",
state          varchar(2)  not null comment "ステータス 00:未処理 01:決済中 99:決済完了",
customerID     varchar(16) not null comment "顧客コード",
itemcode       varchar(16) not null comment "商品コード",
quantity       varchar(10) not null comment "数量",
lastupdate     varchar(14) not null comment "最終更新日時",
createtime     varchar(14) not null comment "登録日時");

3-3 サンプルデータ
insert into  ttg_cart
( invoice, state, customerID, itemcode, quantity, lastupdate, createtime ) values
('000001','00','0000000000000100','0000000000000200',3,'20191008164520','20191008164520'),
('000002','00','0000000000000100','0000000000000300',3,'20191008164520','20191008164520'),
('000003','00','0000000000000100','0000000000000400',3,'20191008164520','20191008164520'),
('000004','00','0000000000000100','0000000000000600',3,'20191008164520','20191008164520'),
('000005','00','0000000000000200','0000000000020100',4,'20191008174520','20191008164520'),
('000006','00','0000000000000200','0000000000020200',4,'20191008174520','20191008164520'),
('000007','00','0000000000000200','0000000000020100',4,'20191008174520','20191008164520'),
('000008','00','0000000000000300','0000000000030200',5,'20191008184520','20191008164520'),
('000009','00','0000000000000300','0000000000030300',5,'20191008184520','20191008164520'),
('000010','00','0000000000000300','0000000000030400',5,'20191008184520','20191008164520'),
('000011','00','0000000000000400','0000000000040100',6,'20191008194520','20191008164520'),
('000012','00','0000000000000400','0000000000040200',6,'20191008194520','20191008164520'),
('000013','00','0000000000000400','0000000000040300',6,'20191008194520','20191008164520');


4. 起動
4-1 起動前準備

1) キャシュクリア
$ vi clean
rm -f  api/migrations/000?_initial.py
rm -f  api/migrations/000?_auto_*.py
rm -rf api/migrations/__pycache__

2) マイグレションと起動
$ vi build
echo python36 manage.py makemigrations-------------------------------
python36 manage.py makemigrations

echo python36 manage.py migrate--------------------------------------
python36 manage.py migrate

echo python36 manage.py createsuperuser------------------------------
python36 manage.py createsuperuser

echo python36 manage.py runserver 0.0.0.0:8000-----------------------
python36 manage.py runserver 0.0.0.0:8000

4-2 起動
$ ./clean
$ ./build
ユーザID、mail、パスワード入力

2019年9月19日木曜日

WebAPI Django REST フレームワーク

【フレームワーク種】
modelsに結びつかない
1)関数ベース    @api_views
2)クラスベース  APIView

modelsに結びつく
3)Generic.view
4) ViewSets


【認証】
JWT token 解析サイト
https://jwt.io/

$ pip3 install djangorestframework djangorestframework-jwt

settings.py

REST_FRAMEWORK = {
  'DEFAULT_PERMISSION_CLASSES': (
    'rest_framework.permissions.IsAuthenticated',
  ),
  'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
  ),
}

JWT_AUTH = {
    'JWT_SECRET_KEY': SECRET_KEY,
    'JWT_ALGORITHM': 'HS256',
    'JWT_ALLOW_REFRESH': True,
    'JWT_EXPIRATION_DELTA': timedelta(days=7),
    'JWT_REFRESH_EXPIRATION_DELTA': timedelta(days=28),
}

urls.py
urlpatterns = [ 
    path('token/', obtain_jwt_token),
    path('token/verify/', verify_jwt_token),
    path('token/refresh/', refresh_jwt_token),
]


$ curl -X POST http://localhost:8000/api/token/
{"email":["この項目は必須です。"],"password":["この項目は必須です。"]}
$ curl -X POST http://localhost:8000/api/token/ -d  "password=no3177&email=takahab@cxdnext.co.jp"

{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6InRha2FoYWJAY3hkbmV4dC5jby5qcCIsImV4cCI6MTU2OTQ3MDI2OCwiZW1haWwiOiJ0YWthaGFiQGN4ZG5leHQuY28uanAiLCJvcmlnX2lhdCI6MTU2ODg2NTQ2OH0.w_eU3AA73tMssNm0u9E3vYHml6tt76ev50vJNRBaw28"}

$ curl -X POST http://localhost:8000/api/v1/register/ -H "Authorization:JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6InRha2FoYWJAY3hkbmV4dC5jby5qcCIsImV4cCI6MTU2OTQ3NzUyNCwiZW1haWwiOiJ0YWthaGFiQGN4ZG5leHQuY28uanAiLCJvcmlnX2lhdCI6MTU2ODg3MjcyNH0.fNvVi3fIaayZ3_9bhhpdAxLhQCg3dATdIYO_85qiwro"


認証情報が届かないようだ。
{"detail":"認証情報が含まれていません。"}
vi /etc/httpd/conf.d/wsgi.conf
WSGIPassAuthorization on

これを追加すると認証できた。


【クライアントサンプルアプリ】
#!/usr/bin/env python36
# coding=utf-8
import json
import urllib.request

def get_token():
  auth_url = 'http://localhost:8000/api/token/'
  auth_data = {'password':'password','email':'mail@address.jp'}
  data = urllib.parse.urlencode(auth_data).encode('utf-8')

  obj = urllib.request.Request(auth_url, data=data, method='POST')
 
  return( __urlopen( obj ) )

def api_req( req, token ):
  url = 'http://localhost:8000/api/v1/register/'
  headers = { 'Content-Type' : 'application/json',
              'Authorization': 'JWT {0}'.format(token[ 'token' ])}
  json_data = json.dumps(req).encode('utf-8')

  obj = urllib.request.Request(url, data=json_data, method='POST', headers=headers)

return( __urlopen( obj ) )

def __urlopen( obj ):
  body = {}
  try:
    with urllib.request.urlopen(obj) as res:
    body = json.load(res)
  except urllib.error.HTTPError as err:
    body['ERROR'] = {}
    body['ERROR'][ 'code' ] = err.code
    body['ERROR'][ 'reason' ] = err.reason
    body['ERROR'][ 'headers'] = err.headers
  except urllib.error.URLError as err:
    body['ERROR'] = {}
    body['ERROR'][ 'reason' ] = err.reason 
  return body


def main():
  import io, sys
  sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

  req = {
        "version" : "01-01",
        "requestID": "0001",
        "name" : "inquiry",
        "sender" : "VR-200 No1",
        "category" : "registerAPI",
        "messages" : "伝票の問い合わせ",
        "descriptions": [{"customerID":"0000000000000100"}],
        "status" : "200"
  }

  token = get_token()

  if( 'token' in token):
    print( 'SEND REQUEST = ', json.dumps( req, indent=2, ensure_ascii=False) )
    body = api_req( req, token )

  if( 'ERROR' in token ):
    for key, val in token['ERROR'].items():
      print ( 'ERROR', key,':',val )
  elif( 'ERROR' in body ):
    for key, val in body['ERROR'].items():
      print ( 'ERROR' ,key,':',val )
  else:
    print( 'RESPONSE = ' , json.dumps(body, indent=2, ensure_ascii=False ))

if __name__ == "__main__":
main()

2019年8月20日火曜日

vimカスタマイズ

【viで文字コードを指定して再読込】
:e ++enc=shift_jis                       [ shift_jis / utf-8 / euc-jp 】


# vi ~/.vimrc
set encoding=utf-8
set fileencoding=utf-8
scriptencoding utf-8
set paste
set number
"-----------------------------------------------------------
" TABキーを押した際にタブ文字の代わりにスペースを入れる
set expandtab
set tabstop=2
set shiftwidth=2
"-----------------------------------------------------------
" Jsonファイルを表示。
" command :Jq
"-----------------------------------------------------------
command! -nargs=? Jq call s:Jq(<f-args>)
function! s:Jq(...)
  if 0 == a:0
    let l:arg = "."
  else
    let l:arg = a:1
  endif
execute "%! jq \"" . l:arg . "\""
endfunction
"xml 整形
command Xml :%s/></>\r</g | filetype indent on | setf xml | normal gg=G

"-----インデンドの可視化------------------------------------
" command : set list / set nolist
"-----------------------------------------------------------
hi SpecialKey ctermfg=darkmagenta
set listchars=tab:¦_,trail:-,eol:↲,extends:»,precedes:«,nbsp:%

"--------neobundle.vim--------------------------------------
if &term =~ "xterm"
  let &t_SI .= "\e[?2004h"
  let &t_EI .= "\e[?2004l"
  let &pastetoggle = "\e[201~"

  function XTermPasteBegin(ret)
    set paste
    return a:ret
  endfunction
  inoremap <special> <expr> <Esc>[200~ XTermPasteBegin("")
endif

if has('vim_starting')
  " 初回起動時のみruntimepathにNeoBundleのパスを指定する
  set runtimepath+=~/.vim/bundle/neobundle.vim/

  " NeoBundleが未インストールであればgit cloneする・・・・・・①
  if !isdirectory(expand("~/.vim/bundle/neobundle.vim/"))
    echo "install NeoBundle..."
    :call system("git clone git://github.com/Shougo/neobundle.vim ~/.vim/bundle/neobundle.vim")
  endif
endif

call neobundle#begin(expand('~/.vim/bundle/'))

"----------------------------------------------------------
" インストールするVimプラグインを以下に記述
" NeoBundle自身を管理
NeoBundleFetch 'Shougo/neobundle.vim'
"----------------------------------------------------------
" ここに追加したいVimプラグインを記述する・・・・・・②

" カラースキームmolokai
NeoBundle 'tomasr/molokai'
" カラースキームrupza
NeoBundle 'felipesousa/rupza'
" ステータスラインの表示内容強化
NeoBundle 'itchyny/lightline.vim'

" 末尾の全角と半角の空白文字を赤くハイライト
" command :FixWhitespce
NeoBundle 'bronson/vim-trailing-whitespace'

" インデントの可視化
NeoBundle 'Yggdroot/indentLine'
"----------------------------------------------------------
call neobundle#end()
"----------------------------------------------------------
" ファイルタイプ別のVimプラグイン/インデントを有効にする
filetype plugin indent on
" 未インストールのVimプラグインがある場合、インストールするかどうかを尋ねてくれるようにする設定・・・・・・③
NeoBundleCheck

"----------------------------------------------------------
" colorschemeの設定
"----------------------------------------------------------
if neobundle#is_installed('molokai') " molokaiがインストールされていれば
" colorscheme molokai " カラースキームにmolokaiを設定する
  colorscheme rupza " カラースキームにrupzaを設定する
endif
set t_Co=256 " iTerm2など既に256色環境なら無くても良い
syntax enable " 構文に色を付ける

"----------------------------------------------------------
" ステータスラインの設定
"----------------------------------------------------------
set laststatus=2 " ステータスラインを常に表示
set showmode " 現在のモードを表示
set showcmd " 打ったコマンドをステータスラインの下に表示
set ruler " ステータスラインの右側にカーソルの現在位置を表示する

" indentLine
let g:indentLine_color_term = 111
let g:indentLine_color_gui = '#708090'
let g:indentLine_char = '¦'

2019年8月15日木曜日

CentOS7 /homeを別ディスクにマウント

root でログイン
# userdel -r xxxxx              /home以下のユーザを削除
# ls -l /home
total 0                         確認
# umount /home

# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table
Building a new DOS disklabel with disk identifier 0xab90547f.

The device presents a logical sector size that is smaller than
the physical sector size. Aligning to a physical sector (or optimal
I/O) size boundary is recommended, or performance may be impacted.

コマンド (m でヘルプ): m
コマンドの動作
   a   toggle a bootable flag
   b   edit bsd disklabel
   c   toggle the dos compatibility flag
   d   delete a partition
   g   create a new empty GPT partition table
   G   create an IRIX (SGI) partition table
   l   list known partition types
   m   print this menu
   n   add a new partition
   o   create a new empty DOS partition table
   p   print the partition table
   q   quit without saving changes
   s   create a new empty Sun disklabel
   t   change a partition's system id
   u   change display/entry units
   v   verify the partition table
   w   write table to disk and exit
   x   extra functionality (experts only)

コマンド (m でヘルプ): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
パーティション番号 (1-4, default 1):
最初 sector (2048-976773167, 初期値 2048):
初期値 2048 を使います
Last sector, +sectors or +size{K,M,G} (2048-976773167, 初期値 976773167):
初期値 976773167 を使います
Partition 1 of type Linux and of size 465.8 GiB is set

コマンド (m でヘルプ): t
Selected partition 1
Hex code (type L to list all codes): L

 0  空              24  NEC DOS         81  Minix / 古い Li bf  Solaris       
 1  FAT12           27  Hidden NTFS Win 82  Linux スワップ  c1  DRDOS/sec (FAT-
 2  XENIX root      39  Plan 9          83  Linux           c4  DRDOS/sec (FAT-
 3  XENIX usr       3c  PartitionMagic  84  OS/2 隠し C: ド c6  DRDOS/sec (FAT-
 4  FAT16 <32M      40  Venix 80286     85  Linux 拡張領域  c7  Syrinx        
 5  拡張領域        41  PPC PReP Boot   86  NTFS ボリューム da  非 FS データ  
 6  FAT16           42  SFS             87  NTFS ボリューム db  CP/M / CTOS / .
 7  HPFS/NTFS/exFAT 4d  QNX4.x          88  Linux プレーン  de  Dell ユーティリ
 8  AIX             4e  QNX4.x 2nd part 8e  Linux LVM       df  BootIt        
 9  AIX ブート可能  4f  QNX4.x 3rd part 93  Amoeba          e1  DOS access    
 a  OS/2 ブートマネ 50  OnTrack DM      94  Amoeba BBT      e3  DOS R/O       
 b  W95 FAT32       51  OnTrack DM6 Aux 9f  BSD/OS          e4  SpeedStor     
 c  W95 FAT32 (LBA) 52  CP/M            a0  IBM Thinkpad ハ eb  BeOS fs       
 e  W95 FAT16 (LBA) 53  OnTrack DM6 Aux a5  FreeBSD         ee  GPT           
 f  W95 拡張領域 (L 54  OnTrackDM6      a6  OpenBSD         ef  EFI (FAT-12/16/
10  OPUS            55  EZ-Drive        a7  NeXTSTEP        f0  Linux/PA-RISC 
11  隠し FAT12      56  Golden Bow      a8  Darwin UFS      f1  SpeedStor     
12  Compaq 診断     5c  Priam Edisk     a9  NetBSD          f4  SpeedStor     
14  隠し FAT16 <32M 61  SpeedStor       ab  Darwin ブート   f2  DOS セカンダリ
16  隠し FAT16      63  GNU HURD または af  HFS / HFS+      fb  VMware VMFS   
17  隠し HPFS/NTFS  64  Novell Netware  b7  BSDI fs         fc  VMware VMKCORE
18  AST SmartSleep  65  Novell Netware  b8  BSDI スワップ   fd  Linux raid 自動
1b  隠し W95 FAT32  70  DiskSecure Mult bb  隠し Boot Wizar fe  LANstep       
1c  隠し W95 FAT32  75  PC/IX           be  Solaris ブート  ff  BBT           
1e  隠し W95 FAT16  80  古い Minix    
Hex code (type L to list all codes): 8e
Changed type of partition 'Linux' to 'Linux LVM'

コマンド (m でヘルプ): w
パーティションテーブルは変更されました!
ioctl() を呼び出してパーティションテーブルを再読込みします。
ディスクを同期しています。

# fdisk -l /dev/sdb
Disk /dev/sdb: 500.1 GB, 500107862016 bytes, 976773168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O サイズ (最小 / 推奨): 4096 バイト / 4096 バイト
Disk label type: dos
ディスク識別子: 0xab90547f

デバイス ブート      始点        終点     ブロック   Id  システム
/dev/sdb1            2048   976773167   488385560   8e  Linux LVM

# pvcreate /dev/sdb1
  Physical volume "/dev/sdb1" successfully created.
# pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda2
  VG Name               centos
  PV Size               <222.57 GiB / not usable 3.00 MiB
  Allocatable           yes
  PE Size               4.00 MiB
  Total PE              56977
  Free PE               1
  Allocated PE          56976
  PV UUID               IbFRgF-14az-CyYG-Vq0o-JRll-rEPl-TwfdZA
  
  "/dev/sdb1" is a new physical volume of "465.76 GiB"
  --- NEW Physical volume ---
  PV Name               /dev/sdb1
  VG Name              
  PV Size               465.76 GiB
  Allocatable           NO
  PE Size               0  
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               wSOMkJ-a57d-M5Ko-F5PG-TktP-Gm6g-KkozMu
  
# vgcreate lvguserdata /dev/sdb1
  /dev/sdc: open failed: メディアが見つかりません
  /dev/sdd: open failed: メディアが見つかりません
  /dev/sde: open failed: メディアが見つかりません
  /dev/sdf: open failed: メディアが見つかりません
  Volume group "lvguserdata" successfully created
# vgdisplay
  --- Volume group ---
  VG Name               lvguserdata
  System ID            
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  1
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                0
  Open LV               0
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               <465.76 GiB
  PE Size               4.00 MiB
  Total PE              119234
  Alloc PE / Size       0 / 0  
  Free  PE / Size       119234 / <465.76 GiB
  VG UUID               8CFNUB-wlEk-JOA2-LtDn-YzBN-dL0U-mDiQKM
  
  --- Volume group ---
  VG Name               centos
  System ID            
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  4
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                3
  Open LV               3
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               <222.57 GiB
  PE Size               4.00 MiB
  Total PE              56977
  Alloc PE / Size       56976 / 222.56 GiB
  Free  PE / Size       1 / 4.00 MiB
  VG UUID               ZUzbN5-dx4i-qR5d-wNxD-ejeB-9syW-aRtbgC
  
# vgscan
  Reading volume groups from cache.
  Found volume group "lvguserdata" using metadata type lvm2
  Found volume group "centos" using metadata type lvm2
[root@localhost dev]# lvcreate --name home -l 100%FREE lvguserdata
  Logical volume "home" created.
[root@localhost dev]# lvdisplay lvguserdata
  --- Logical volume ---
  LV Path                /dev/lvguserdata/home
  LV Name                home
  VG Name                lvguserdata
  LV UUID                oatwnX-vjXB-hgXp-DNfo-zc1W-wUJO-rBJwGH
  LV Write Access        read/write
  LV Creation host, time localhost.localdomain, 2019-08-15 19:58:48 +0900
  LV Status              available
  # open                 0
  LV Size                <465.76 GiB
  Current LE             119234
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:3
  
# mkfs.xfs /dev/lvguserdata/home
meta-data=/dev/lvguserdata/home  isize=512    agcount=4, agsize=30523904 blks
         =                       sectsz=4096  attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=122095616, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=59617, version=2
         =                       sectsz=4096  sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
# vi /etc/fstab
/dev/mapper/lvguserdata-home /home              xfs     defaults        0 0
# ls -l /dev/centos
合計 0
lrwxrwxrwx. 1 root root 7  8月 15 19:21 home -> ../dm-2
lrwxrwxrwx. 1 root root 7  8月 15 19:21 root -> ../dm-0
lrwxrwxrwx. 1 root root 7  8月 15 19:21 swap -> ../dm-1

# lvremove /dev/centos/home
# lvdisplay centos
# lvextend -l +100%FREE /dev/centos/root
# df
# xfs_growfs /dev/centos/root
# df


2019年8月1日木曜日

Oracleが ロックした。セッションをKILL →切れない ORA-00031: session marked for kill

$ alias sqlplus='rlwrap -pRed -if /usr/local/opt/rlwrap-extensions/sqlplus sqlplus64'
$ sqlplus user/password@192.168.1.xxx:1521/sid
SQL> SELECT s.sid,s.serial#, s.username, s.program FROM V$SESSION s where s.username='ARCSDBSS' and s.program='python36@buffy3 (TNS V1-V3)';

SQL> select s.sid, s.serial#, s.username, s.osuser, s.machine, s.terminal, s.program, o.object_name from v$session s, v$locked_object l, dba_objects o where s.sid = l.session_id and l.object_id = o.object_id;

SQL> alter system kill session 'sid, serial#'

killedになったが切れない。
ORA-00031: session marked for kill

ALTER SYSTEM DISCONNECT SESSION 'sid,serialNo' {POST_TRANSACTION | IMMEDIATE};
ERROR at line 1:
ORA-00031: session marked for kill

すぐ返って来るけど同じだ!!!!

select spid, s.sid, s.serial#, s.status , osuser, s.program,s.username, s.event from
v$process p, v$session s where p.addr=s.paddr and s.status = 'KILLED';

列幅調整
COLUMN spid FORMAT a5 TRUNCATE

2019年7月11日木曜日

pythonでexcelを読んでみた。便利

#!/usr/bin/env python36
# coding=utf-8
import openpyxl as excel
import json
import gzip
#import pickle

def excel2dic( filename ):
    wb = excel.load_workbook( filename )
    context = {}
    for sheet in wb.get_sheet_names():
        ws = wb.get_sheet_by_name(sheet)
        columns = [ row.value for row in list(ws.rows)[0]]
        dic  = [ dict(zip(columns, [ ws.cell(column=cell.col_idx, row=cell.row).value for cell in row ])) for row in ws.rows]
        dic.pop(0)
        context[ sheet ] = dic
    wb.close()
    return context

def excel_getsheetnames( filename ):
    wb = excel.load_workbook( filename )
    sheets = wb.get_sheet_names()
    wb.close()
    return sheets

def create_sql_insert( context ):
    sql =''
    for sheet in context.keys():
        for n in range( len( context[ sheet ])):
            s1 = str(list(context[ sheet ][n].keys())).replace('[','').replace(']','')
            s2 = str(list(context[ sheet ][n].values())).replace('[','').replace(']','')
            sql = sql + 'into {0} ( {1} ) values ({2})\n'.format( sheet, s1, s2)

    sql = 'SAVEPOINT;INSERT ALL\n{0}SELECT * DUAL'.format( sql )
    return sql

def create_sql_delete( gcode, ccode, scode, context  ):
    sql = 'SAVEPOINT;\n'
    for sheet in context.keys():
        sql = sql + 'DELETE FROM {0} WHERE GCODE={1} and CCODE={2} and SCODE={3}; \n'.format( sheet, gcode, ccode, scode)
    return sql

def create_sql_update( gcode, ccode, scode, context  ):
    comma=''
    sql =''
    for sheet, value in context.items():
        s=''
        for n in range( len( context[ sheet ])):
            for k, v in value[n].items():
                s = s + comma + '{1} = "{2}" '.format( sheet, k, v)
                comma = ','
        sql = sql + 'UPDATE {0} SET {4} WHERE  GCODE={1} and CCODE={2} and SCODE={3}; \n'.format( sheet, gcode, ccode, scode, s )
    return sql

def main():
    context = excel2dic( 'test.xlsx')
    sql = create_sql_insert( context )
    print( sql )
    sql = create_sql_delete( '"101"', '"1234"', '"1234"', context )
    print( sql )
    sql = create_sql_update( '"101"', '"1234"', '"1234"', context )
    print( sql )
    enc = json.dumps( context )
    with gzip.open( 'backup.gz', mode='wb', compresslevel=9) as fp:
        fp.write( enc.encode() )

    print( excel_getsheetnames( 'test.xlsx' ))

if __name__ == "__main__":
    main()

2019年6月24日月曜日

zabbixのレコード数を確認

mysql> select table_name, table_rows from information_schema.TABLES where table_schema = 'zabbix';

2019年6月14日金曜日

Zabbix history_uint.ibd 肥大化して困った。

history_uint.ibdが肥大化して52Gになった。

-rw-r-----. 1 mysql mysql 52495908864  6月 14 09:20 history_uint.ibd
-rw-r-----. 1 mysql mysql  7977566208  6月 14 09:20 trends_uint.ibd



# /etc/init.d/zabbix-server stop

1.現テーブルをコピーして別テーブルで保存(1週間分)

timestampについては以下

https://www.epochconverter.com/

mysql> CREATE TABLE history_uint_new LIKE history_uint;
mysql> INSERT INTO history_uint_new SELECT * FROM history_uint WHERE clock > 'xxxxxxxxxx';

2.コピーした別テーブルを現テーブルに移行

mysql> ALTER TABLE history_uint RENAME history_uint_old;
mysql> ALTER TABLE history_uint_new RENAME history_uint;

5.zabbix-server 起動
# /etc/init.d/zabbix-server start

2019年5月30日木曜日

ssh keysを作ってみた。(ssh 公開鍵認証)

【AWS EC2  guacamole 】

# useradd takahab
# passwd takahab
$ su - takahab
$ mkdir .ssh
$ chmod 0700 .ssh
$ cd .ssh
$ ssh-keygen -t rsa -b 4096 -m PEM
$ vi authorized_keys     <-- id_rsa.pubをコピー
$ chmod 0600  authorized_keys

※ keepAlive
$ ssh -o ServerAliveInterval=60  -p 22 target_host

# vi /etc/ssh/sshd_config
ClientAliveInterval 120
ClientAliveCountMax 3


【クライアント側】
[$ ssh-keygen -t ed25519]      # githubの場合

※ 一時的にサーバ側でパス認証を許可して上で実施。

$ ssh-keygen -t rsa -b 4096 -C "email@example.com"
$ ssh-keygen -l -f ~/.ssh/id_rsa.pub        # 確認
$ ssh-copy-id -i ~/.ssh/id_rsa.pub -p 65522 $REMOTE
$ ssh -i id_rsa -p 65522 $REMOTE

※接続できない場合は、
$ ssh -v       -p 65522 $REMOTE
$ ssh -vvv  -p 65522 $REMOTE
ログ確認
#  vi /var/log/secure
# vi  /var/log/ssh/sshd.log

【サーバ側】
$ su
# vi /etc/ssh/sshd_config
PermitRootLogin を no                                          # root ログイン禁止
PasswordAuthentication no                                # パスワード認証禁止(公開鍵認証のみ) 
PermitEmptyPasswords  no                                # パスワード無し禁止( パスワード認証の場合)
# systemctl restart sshd

ーーーーーー以下 参考ーーーーーーーーー
【サーバ側】
$ cp id_rsa.pub
$ vi  ~/.ssh/authorized_keys
id_rsa.pub をコピー&ペイスト 
$ chmod 600 authorized_keys

【作成】
# useradd user
$ cd 
$ ssh-keygen -t rsa -b 4096 -C "email@example.com"
【確認】
$ ssh-keygen -l -f ~/.ssh/id_rsa.pub

【配信】
#ssh-copy-id -i ~/.ssh/id_rsa.pub root@remote.com -p 22

久しぶりに公開鍵を作ってみた。

$ openssl genrsa 4096 > private-key.pem
$ openssl rsa -in private-key.pem -pubout -out public-key.pem

$ openssl rsa -in private-key.pem -text -noout
$ openssl rsa -pubin -in public-key.pem -text -noout

2019年5月15日水曜日

goaccessを使ってみた。

# yum install goaccess
# vi /etc/goaccess.conf
time-format %H:%M:%S
date-format %d/%b/%Y
log-format %h %^[%d:%t %^] "%r" %s %b "%R" "%u"

# goaccess /var/log/httpd/access_log*
# goaccess /var/log/httpd/access_log* >/var/www/html/reports.html

2019年5月7日火曜日

mysqldが起動できない。 ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)

[System][MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.16) starting as process 20744
[System][MY-013381] [Server] Server upgrade from '80015' to '80016' started.
[ERROR][MY-013384] [Server] Could not create server upgrade info file at '/var/lib/mysql/'.
[ERROR][MY-013380] [Server] Failed to upgrade server.
[ERROR][MY-010119] [Server] Aborting


【対処】
# mv /var/lib/mysql/mysql_upgrade_info /var/lib/mysql/mysql_upgrade_info.bak
# systemctl start mysqld


# vi /var/log/mysqld.log

[System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.16) starting as process 21873
[System] [MY-013381] [Server] Server upgrade from '80015' to '80016' started.
[System] [MY-013381] [Server] Server upgrade from '80015' to '80016' completed.

無事起動した。
※8.0.16からデータベースのアップグレードが自動になったもよう。

ssh 中継

【AWS EC2中継】
$ vi  ~/.ssh/config    << __EOF__
host aws.step
  HostName xx.xx.xx.xx
  Port 22
  User ec2-user
  IdentityFile ~/.ssh/step.pem

Host aws.utlsv
  HostName xx.xx.xx.xx
  Port 22
  User ec2-user
  ProxyCommand ssh aws.step -W %h:%p
  IdentityFile ~/.ssh/utlsv.pem
__EOF__

接続したいホストと中継サーバ間にトンネル生成
$ ssh www.gateway.com -R 10022:192.168.1.100:22
※autosshコマンドでを使えば、切断時も自動再接続してくれる。

遠隔から
$ ssh www.gateway.com
$ ssh localhost -p 10022

tmux仮想端末でマルチ画面

cntl+b c   ウィンドウ作成
cntl+b 1-n ウィンドウ指定
cntl+b p   ウィンドウ切り替え



データベース開発ツールDBeaverのインストール

https://dbeaver.io/
上記からDBeaver 6.0.4をダウンロード

# rpm -ivh dbeaver-ce-6.0.4-stable.x86_64.rpm

jdbcドライバをインストール。
# cp ojdbc6.jar /opt/libs/oracle/ojdbc6.jar


バージョンアップ
# rpm -qa |grep dbea
dbeaver-ce-6.0.4-stable.x86_64
# rpm -qi dbeaver-ce
# rpm -Uvh dbeaver-ce-6.1.1-stable.x86_64.rpm

[splash]
~/.eclipse/org.jkiss.dbeaver.product_22.3.2_302967072_linux_gtk_x86_64/configuration/org.eclipse.equinox.launcher/org.jkiss.dbeaver.ui.app.standalone_22.3.2.202301060755



2019年4月9日火曜日

CentOS7 に sqlplus インストール

https://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html

oracle-instantclient 18.5-basic-18.5.0.0.0-3.x86_64.rpm
oracle-instantclient18.5-sqlplus-18.5.0.0.0-3.x86_64.rpm

# yum install -y libaio
# rpm -ivh oracle-instantclient18.5-basic-18.5.0.0.0-3.x86_64.rpm
# rpm -ivh oracle-instantclient18.5-sqlplus-18.5.0.0.0-3.x86_64.rpm
# ls -l /usr/lib/oracle/18.5/client64/lib 確認
# echo "/usr/lib/oracle/18.5/client64/lib" >> /etc/ld.so.conf.d/oracle.conf
# cat !$ 確認
# ldconfig
# sqlplus64

SQL*Plus: Release 18.0.0.0.0 - Production on Tue Apr 9 19:01:08 2019
Version 18.5.0.0.0
Copyright (c) 1982, 2018, Oracle. All rights reserved.
Enter user-name:

[カーソルキーを使えるようにする]
# yum -y install rlwrap
# mkdir  -p /usr/local/opt/rlwrap-extensions
# cd /usr/local/opt/rlwrap-extensions
# wget http://www.linuxification.at/download/rlwrap-extensions-V11-0.05.tar.gz (11gの場合)
# tar xzvf rlwrap-extensions-V11-0.05.tar.gz     <-辞書
# vi /etc/profile.d/oracle.sh  
alias sqlplus='rlwrap -pRed -if /usr/local/opt/rlwrap-extensions/sqlplus sqlplus'


[12g]
# wget http://www.linuxification.at/download/rlwrap-extensions-V12-0.05.tar.gz (12gの場
# tar xzvf rlwrap-extensions-V12-0.05.tar.gz     <-辞書
# vi /usr/local/opt/rlwrap-extensions/sql+
R_HOME=${RLWRAP_HOME:=/usr/local/opt/rlwrap-extensions}
# cd /usr/local/bin
# ln -s  /usr/local/opt/rlwrap-extensions/asm+ asm+
# ln -s  /usr/local/opt/rlwrap-extensions/sql+ sql+

※ rlwap インストールには、epel リポジトリが必要。
[rocky]
# dnf config-manager --set-enabled powertools
# dnf install epel-release

[参考]



$ sqlplus user/password@192.168.1.xxx:1521/sid
$ sqlplus  system/oracle@192.168.25.131:1521/arcsdbms

SQL> @calc.sql
 13 ;

[sample]
$ vi calc.sql
with
CALC as (
SELECT
TO_DATE('20190405', 'yyyymmdd') - (ROWNUM - 1) as cdate
FROM ALL_CATALOG
WHERE TO_DATE('20190405', 'yyyymmdd') - (ROWNUM - 1) >= TO_DATE('20190315', 'yyyymmdd')
ORDER BY 1 desc
)
select
TO_CHAR(c.cdate, 'yyyymmdd') as cdate,
'('||SUBSTR(TO_CHAR(c.cdate, 'day','NLS_DATE_LANGUAGE=JAPANESE'),1,1)||')' as cday
from CALC c

2019年3月1日金曜日

yum proxy経由で使う。

【プロキシサーバの設定】
# dnf install squid
# vi /etc/squid/squid.conf
# add by takahab for dnf proxy                        ※末尾に追加
shutdown_lifetime 0 seconds
http_port 3128
http_port 0.0.0.0:3128
http_access allow all

# firewall-cmd --add-port=3128/tcp --zone=public --permanent
# firewall-cmd --reload
# systemctl restart squid
# systemctl enable squid

【プロキシサーバの設定】
# yum install squid
# vi /etc/squid/squid.conf
#http_access deny all
#http_port 3128
http_port 3128
acl myacl src 142.1.5.250/255.255.255.255
http_access allow myacl
http_access deny all
header_access X-Forwarded-For deny all
header_access Via deny all
header_access Cache-Control deny all

# systemctl restart squid
# firewall-cmd --add-port=3128/tcp --zone=public --permanent
# firewall-cmd --reload
# systemctl enable squid

【クライアントの設定】
yum のプリキシ設定
# vi /etc/yum.conf
proxy=http://192.168.1.1
#proxy=http://192.168.1.1
#proxy_username=user_name
#proxy_password=password

2019年2月19日火曜日

Django python pyreportjasperで日本語フォントを使う。

jasperstudioから、フォントをexportして、JasperStarter/jdbc下に配置する。

jasperstudio
プロジェクト名->プロパティ->Jasperstudio->Fonts->Use Project Settings
add from path
/usr/share/fonts/ipa-gothic
/usr/share/fonts/ipa-pgothic
/usr/share/fonts/ipa-mincho
/usr/share/fonts/ipa-pmincho
全て選択して、export
export ipa_Fonts.jar されたファイルを下記に配置。
mv ipa_Fonts.jar /usr/local/venv36/lib/python3.6/site-packages/pyreportjasper/jasperstarter/jdbc


2019年1月8日火曜日

Django debug -toolbar のインストール

$ pip3 install django-debug-toolbar
$ vi Project/urls.py  <<__EOF__
from django.conf import settings
from django.conf.urls import include, url

if settings.DEBUG:
    import debug_toolbar
    urlpatterns += [
        url(r'^__debug__/', include(debug_toolbar.urls)),
    ]
__EOF__
$ vi Project/settings.py  <<__EOF__
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',  # これがあることを確認(なければ追加)
    'debug_toolbar',  # 追加
    ]
MIDDLEWARE = [
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'debug_toolbar.middleware.DebugToolbarMiddleware',  # 追加
]

# Debug Toolbar

DEBUG = True

if DEBUG:
    INTERNAL_IPS = ['127.0.0.1', 'localhost']

    def custom_show_toolbar(request):
        return True

    DEBUG_TOOLBAR_PANELS = [
        'debug_toolbar.panels.timer.TimerPanel',
        'debug_toolbar.panels.request.RequestPanel',
        'debug_toolbar.panels.sql.SQLPanel',
        'debug_toolbar.panels.templates.TemplatesPanel',
        'debug_toolbar.panels.cache.CachePanel',
        'debug_toolbar.panels.logging.LoggingPanel',
    ]

    DEBUG_TOOLBAR_CONFIG = {
        'INTERCEPT_REDIRECTS': False,
        'SHOW_TOOLBAR_CALLBACK': custom_show_toolbar,
        'HIDE_DJANGO_SQL': False,
        'TAG': 'div',
        'ENABLE_STACKTRACES': True,
    }
__EOF__
$ python36 manage.py collectstatic
$ mv assets/debug_toolbar static/
$ rm -r assets
これで完了

2019年1月7日月曜日

Django データベースをmysql に変更

# pip3 install pymysql
# pip3 install mysql-connector-python
# pip3 freeze -l # <--インストールモジュールの確認
cx-Oracle==7.0.0
Django==2.1.5
django-crispy-forms==1.7.2
django-filter==2.0.0
et-xmlfile==1.0.1
jdcal==1.4
mod-wsgi==4.6.5
mod-wsgi-httpd==2.4.35.1
mysql-connector-python==8.0.13
openpyxl==2.5.12
protobuf==3.6.1
PyMySQL==0.9.3
pytz==2018.5
six==1.12.0

$ vi config/settings.py
DATABASES = {
   'default': {
      'ENGINE': 'django.db.backends.mysql',
      'NAME': 'django', # 作成したデータベース名 予め空DBを作成しておく。
      'USER': 'admin',
      'PASSWORD':'パスワード',
      'HOST': '',
      'PORT': '',
   }
}
$ vi manage.py
import pymysql
pymysql.install_as_MySQLdb()

$ mysql -u admin -p
mysql> create database django;
mysql> quit
$ python36 manage.py makemigrations
$ python36 manage.py migrate
$ python36 manage.py createsuperuser
$ python36 manage.py runserver

※下記エラーが発生。
File "/usr/local/lib64/python3.6/site-packages/pymysql/_auth.py", line 142, in sha2_rsa_encrypt
    raise RuntimeError("cryptography is required for sha256_password or caching_sha2_password")
RuntimeError: cryptography is required for sha256_password or caching_sha2_password

→mysql8にmysql_native_passwordの新しいユーザを作成。
https://wasurenaiyounikaitoko.blogspot.com/2018/10/centos7-mysql.html

django使ってみた。

# yum install python36
$ python36 --version
Python 3.6.6
$ python36
Python 3.6.6 (default, Aug 13 2018, 18:24:23)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.get_version()
'2.1.5'

$ mkdir Django
$ cd Django
$ django-admin startproject Project
$ cd Project
$ python36 manage.py startapp Login
$ python36 manage.py startapp app
$ vi Project/settings.py  <<__EOF__
INSTALLED_APPS = [
   .
   .
  'Login',             # <--追加
]
TEMPLATES = [
    { 
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "templates")],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
__EOF__

■DBをmysqlに変更
$ vi Project/settings.py  <<__EOF__
DATABASES = {
   'default': {
      'ENGINE': 'django.db.backends.mysql',
      'NAME': 'django', # 作成したデータベース名 予め空DBを作成しておく。
      'USER': 'admin',
      'PASSWORD':'パスワード',
      'HOST': '',
      'PORT': '',
   }
}
__EOF__
$ vi manage.py
import pymysql
pymysql.install_as_MySQLdb()

$ mysql -u admin -p
mysql> create database django;
mysql> quit

$ python36 manage.py makemigrations Login
$ python36 manage.py migrate
$ python36 manage.py createsuperuser
$ python36 manage.py runserver

$ python36 manage.py shell                # <-DB操作

■css, javascriptは、BootStrapを利用。
ダウンロードして、static/bootstrap/下に配置。(admin 2を利用)
https://startbootstrap.com/template-categories/all/

$ mkdir static       #  ~/Django/Project下
$ (cd static;unzip ../../startbootstrap-sb-admin-2-gh-pages.zip)
$ (cd static;ln -s startbootstrap-sb-admin-2-gh-pages bootstrap)
$ (cd static/bootstrap;ls | grep -v -E '^dist$|^js$|^vendor$'| xargs rm -r)
$ mkdir templates
$ vi templates/base.html  <<__EOF__
<!DOCTYPE html>
<html lang="ja">
<head>
{% load staticfiles %}
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>{% block title %}{% endblock %}</title>
<link href="{% static 'bootstrap/vendor/bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'bootstrap/vendor/metisMenu/metisMenu.min.css' %}" rel="stylesheet">
<link href="{% static 'bootstrap/dist/css/sb-admin-2.css' %}" rel="stylesheet">
<link href="{% static 'bootstrap/vendor/font-awesome/css/font-awesome.min.css' %}" rel="stylesheet" type="text/css">
<link href="{% static 'app/css/structure.css' %}" rel="stylesheet" type="text/css">
<script type="text/javascript" src="{% static 'bootstrap/vendor/jquery/jquery.min.js' %}"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.0/jquery-ui.min.js"></script>
<script src="{% static 'bootstrap/vendor/bootstrap/js/bootstrap.min.js' %}"></script>
<script src="{% static 'bootstrap/vendor/metisMenu/metisMenu.min.js' %}"></script>
<script src="{% static 'bootstrap/vendor/datatables/js/jquery.dataTables.min.js' %}"></script>
<script src="{% static 'bootstrap/vendor/datatables-plugins/dataTables.bootstrap.min.js' %}"></script>
<script src="{% static 'bootstrap/vendor/datatables-responsive/dataTables.responsive.js' %}"></script>
<script src="{% static 'bootstrap/dist/js/sb-admin-2.js' %}"></script>

<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div id="wrapper">
<nav class="navbar navbar-default navbar-static-top manager-nav no-margin" role="navigation">
<div class="navbar-header">
<a class="navbar-brand">gragragrao Company</a>
</div>
<div class="navbar-default sidebar" role="navigation">
<div class="sidebar-nav navbar-collapse">
<ul class="nav" id="side-menu">
<li><a href="/worker_list/"><i class="fa fa-bar-chart" aria-hidden="true"></i> Worker一覧</a></li>
</ul>
</div>
</div>
</nav>
{% block body %}
{% endblock %}
</div>
</body>
</html>
__EOF__
$ vi templates/worker_list.html  <<__EOF__
{% extends "base.html" %}
{% block title %}Worker List{% endblock %}
{% load staticfiles %}
{% block body %}
<div id="wrapper">
<div id="page-wrapper">
<div class="row">
<div class="col-lg-6 full-width margin-top-20percent" >
<div class="panel panel-default full-width">
<div class="panel-heading">
Edit Help
</div>
<div class="panel-body full-width full-height">
<table id="worker-list-table" class="table table-striped table-bordered table-hover dataTable no-footer dtr-inline full-width">
<thead>
<tr>
<th>ID</th>
<th>名前</th>
<th>性別</th>
<th>誕生日</th>
</tr>
</thead>
<tbody>
{% for worker in workers %}
<tr>
<td>{{worker.id}}</td>
<td>{{worker.person.name}}</td>
<td>{{worker.person.sex}}</td>
<td>{{worker.person.birthday}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function() {
$('#worker-list-table').DataTable({
responsive: true,
// sort機能の無効化
ordering: false,
// ページの表示件数を変更する
displayLength: 20,
});
});
</script>
{% endblock %}
__EOF__
$ vi Project/settings.py  <<__EOF__
# Static file settings
STATIC_ROOT = os.path.join(BASE_DIR, 'assets')

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)
__EOF__
$ mkdir static/app
$ mkdir static/app/css
$ vi static/app/css/structure.css  <<__EOF__
* ---------------------------------------------------------- */
/* general */
/* ---------------------------------------------------------- */

.full-height {
    height: 100%;
}

.full-width {
    width: 100%;
}

.margin-top-20percent {
    margin-top: 20px;
}

.no-margin {
    margin: 0 !important;
}
__EOF__

■ディレクトリ構造
Django
├── Project
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   ├── settings.cpython-36.pyc
│   │   └── urls.cpython-36.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── app
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   ├── admin.cpython-36.pyc
│   │   └── models.cpython-36.pyc
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       └── __init__.cpython-36.pyc
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── manage.py
├── static
│   ├── app
│   │   └── css
│   │       └── structure.css
│   ├── bootstrap
│       ├── dist
│       ├── js
│       └── vendor
└── templates
    ├── base.html
    └── worker_list.html


※参考
https://qiita.com/gragragrao/items/373057783ba8856124f3
https://github.com/gragragrao/manager_project


※ログインを実装したところエラーが発生。
$ python36 manage.py makemigrations
   .
   .
from django.contrib.auth.views import login
ImportError: cannot import name 'login'

->django 2.1から login はloginViewに変わったらしい。

from django.contrib.auth.view import login
from django.contrib.auth import logout
     ↓
from django.contrib.auth.views import ( LoginView, LogoutView )


※マイグレーションでエラーがでた。
$ python36 manage.py makemigrations
You are trying to add a non-nullable field 'identifier' to person without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Quit, and let me add a default in models.py
Select an option: 2

-> app/migrations/配下のファイルを削除


Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

->hijack

※ログイン実行でエラー
if self.request.user.is_authenticated():
TypeError: 'bool' object is not callable

->djangoの古いバージョンでは、methodであったが、今は属性。

request.user.is_authenticated():
    ↓
request.user.is_authenticated:


















シャットダウン時の後処理 (shutdown)

# vi /etc/systemd/system/drop.service [Unit] Description= stop httpgwd DefaultDependencies=no Before=shutdown.target RefuseManualStart=true ...