- 投稿日:2020-11-22T23:45:07+09:00
[VBA]UTF-8のファイルシステムの文字列が255以下であるか判定する関数とUTF-8の文字列をバイト単位でカウントする関数
AnsiからUTF-8へ
最初ANSIでのカウント方法から苦悩は始まり
Accessを始めるまえに簡単にパパッと作る関数ansiLenB Excelも
UTF-16LEのサロゲートペアにあい
発掘 サロゲートペアについて
Excel for Microsoft 365 VBA Win32Apiとスピルを使いすべての文字のUTF-16 UTF-8 SJisの文字コードを取得する
そして今ファイル名の長さと文字コードの問題 プログラマー社長のブログ
まず、文字コードの問題があります。LinuxやMacOSでは、ファイル名は一般的にUTF-8です。WindowsはNTFSではUNICODEらしいのですが、アプリではShift_JIS(CP932)になるらしいです(あまり興味ないので・・・)。そのため、ZIPで固める際に、UTF-8のまま固めると文字化けしてしまいます。仕方ないので、LinuxやMacOSで無理矢理CP932のファイル名でファイルを作ってZIPで固めるとうまくいきます。が、MacOSでCP932のファイル名を作るとOSごと重くなることが多い気がするのでLinuxの方がマシです。。
さて、文字コードの問題をクリアーしたと思うと、今度はファイル名の長さの問題が立ちふさがります。Windowsではパスも含めて256文字までらしいので、長いファイル名はエラーになってしまいます。仕方ないので、長いファイル名は切り詰めるしかないのですが、ASCII文字の切り詰めは簡単ですが、マルチバイト文字の切り詰めは面倒です。適当なところで切ってしまうと文字化けしてしまいます。仕方ないので、C言語などではワイド文字に変換して切り詰めて、またマルチバイトに戻す感じになります。
昔はWindowsはCP932、UNIX系はEUCが多くて、どちらも日本語は2バイトという想定が使える場合が多かったのですが、インターネットが普及して世界各国の文字が共存するようになってきて、マルチバイトは2バイトどころではなくなってしまい、自力で何とかするのは大変になってしまいました。素直にマルチバイト処理ようのライブラリを使うのが良いでしょう・・・。
社長・・・
(中略)これでようやくWindowsで解凍できる見込みのファイル名にすることができます。「見込み」というのは、パスの長さが256文字までなので、展開するディレクトリによってはオーバーしてしまったりする可能性もあるためです。
ちなみに、LinuxなどのUNIX系OSでは、ファイル名の最大長は255バイト。パスの最大長は1023バイト(システムコールに渡す際の制限)と、Windowsよりはかなり扱いやすくなります
つまりLinuxサーバの場合
ファイル名は
文字コードはUTF-8で、
半角で255文字
ということになる。
この半角で255文字というのは全角文字は85字になる。
半角を1バイトとすると3バイトだからだ。
さらにサロゲートペアは4バイトである。
これを明らかにしたのが、
Excel for Microsoft 365 VBA Win32Apiとスピルを使いすべての文字のUTF-16 UTF-8 SJisの文字コードを取得する
こちらのSheetMake2から作成されるシートになる。
このWin32APIの判定精度の範囲では文字列はUTF-8のバイナリに変換される。
これを利用して、バイトでカウントするというものである。
今回も前回と同様、Win32APIを使う。下のコードは前回のものに追加した形で記述している。#If VBA7 Then Declare PtrSafe Function MessageBox Lib "user32" Alias "MessageBoxW" _ (ByVal hwnd As LongPtr, ByVal lpText As LongPtr, _ ByVal lpCaption As LongPtr, ByVal wType As Long) As Long Declare PtrSafe Function GetFocus Lib "user32" () As LongPtr Declare PtrSafe Function GetWindowsDirectory Lib "Kernel32" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long Declare PtrSafe Function GetSystemDirectory Lib "Kernel32" Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long Declare PtrSafe Function GetTempPath Lib "Kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long 'Private Declare PtrSafe Function SetCurrentDirectory Lib "kernel32" (ByVal lpPathName As Long) As Long ' Set rrent Directory Private Declare PtrSafe Function SetCurrentDirectory Lib "Kernel32" Alias _ "SetCurrentDirectoryA" (ByVal CurrentDir As String) As Long 'Private Declare PtrSafe Function SetCurrentDirectory Lib "kernel32.dll" Alias "SetCurrentDirectoryW" (ByVal lpPathName As Long) As Long 'Private Declare PtrSafe Function SetCurrentDirectory Lib "kernel32.dll" Alias "SetCurrentDirectoryA" (ByVal lpPathName As Long) As Long #Else '標準モジュールに以下のDeclare ステートメントを追加 Declare Function MessageBox Lib "user32" Alias "MessageBoxW" _ (ByVal hwnd As Long, ByVal lpText As Long, _ ByVal lpCaption As Long, ByVal wType As Long) As Long Declare Function GetFocus Lib "user32" () As Long Private Declare Function GetWindowsDirectory Lib "kernel32" _ Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, _ ByVal nSize As Long) As Long #End If Private Declare PtrSafe Function MultiByteToWideChar Lib "kernel32.dll" ( _ ByVal CodePage As Long, _ ByVal dwFlags As Long, _ ByVal lpMultiByteStr As LongPtr, _ ByVal cchMultiByte As Long, _ ByVal lpWideCharStr As LongPtr, _ ByVal cchWideChar As Long) As Long Private Declare PtrSafe Function WideCharToMultiByte Lib "kernel32.dll" ( _ ByVal CodePage As Long, _ ByVal dwFlags As Long, _ ByVal lpWideCharStr As LongPtr, _ ByVal cchWideChar As Long, _ ByVal lpMultiByteStr As LongPtr, _ ByVal cchMultiByte As Long, _ ByVal lpDefaultChar As LongPtr, _ ByVal lpUsedDefaultChar As Long) As Long Private Const CP_UTF8 = 65001 Private Const ERROR_INSUFFICIENT_BUFFER = 122& 'UFT-16LE SarrogatePairのコード Sub TestSarrogatePair() ' For Excel ' ActiveCellにサロゲートペア文字が1字入っているとして、 ' その上位サロゲートと下位サロゲートを求めて、試験のために ' MsgBoxExで表示する ' このため、Windows APIを使用する ' UTF-16 LE , BEなら bb(0) bb(1) bb(2) bb(3)になる Dim b As String Dim bb() As Byte Dim Text As String b = ActiveCell.Value bb = b Debug.Print "AscW Result(Dec -> Hex)" & vbTab & Hex(AscW(b)) Debug.Print "&H" & Hex(bb(1)) & Hex(bb(0)) Debug.Print "&H" & Hex(bb(3)) & Hex(bb(2)) Text = ChrW("&H" & Hex(bb(1)) & Hex(bb(0))) & ChrW("&H" & Hex(bb(3)) & Hex(bb(2))) Debug.Print "ChrW(" & "&H" & Hex(bb(1)) & Hex(bb(0)) & ") & ChrW(&H" & Hex(bb(3)) & Hex(bb(2)) & ")" MsgBoxEx Text End Sub 'UTF-16 LE Function UTF16Sarrogate(s As String) Dim bb() As Byte If IsUpperSarrogateCharacter(s) And IsLowerSarrogateCharcter(s) Then bb = s UTF16Sarrogate = "0x" & CStr(Hex(bb(1)) & Hex(bb(0))) & " " & "0x" & CStr(Hex(bb(3)) & Hex(bb(2))) Exit Function Else UTF16Sarrogate = "" End If End Function Function IsUpperSarrogateCharacter(s As String) If Hex(AscW(s)) >= Hex(&HD800) And Hex(AscW(s)) <= Hex(&HDBFF) Then IsUpperSarrogateCharacter = True: Exit Function Else IsUpperSarrogateCharacter = False: Exit Function End If End Function Function IsLowerSarrogateCharcter(s As String) Dim bb() As Byte If IsUpperSarrogateCharacter(s) = True Then bb = s 'Debug.Print Hex("&H" & bb(3) & bb(2)) If Hex("&H" & bb(3) & bb(2)) <= Hex(&HDC00) And Hex("&H" & bb(3) & bb(2)) <= Hex(&HDFFF) Then IsLowerSarrogateCharcter = True: Exit Function Else IsLowerSarrogateCharcter = False: Exit Function End If End If End Function Function VBAAscW(s As String) If AscW(s) < 0 Then VBAAscW = AscW(s) + 65536: Exit Function Else VBAAscW = AscW(s): Exit Function End If End Function ' Shift-Jis Function VBA_ASC(s As String) If isSJIS(s) Then VBA_ASC = Hex(Asc(s)): Exit Function Else VBA_ASC = "": Exit Function End If End Function Function isSJIS(ByVal argStr As String) As Boolean 'https://excel-ubara.com/excelvba4/EXCEL_VBA_403.html Dim sQuestion As String sQuestion = Chr(63) '?:文字リテラルでは誤解があるといけないので Dim i As Long For i = 1 To Len(argStr) If Mid(argStr, i, 1) <> sQuestion And _ Asc(Mid(argStr, i, 1)) = Asc(sQuestion) Then isSJIS = False Exit Function End If Next isSJIS = True End Function Function LenByteUTF8(ByRef s As String) As Long If Len(s) = 0 Then LenByteUTF8 = 0 Exit Function End If Dim nBufferSize As Long Dim Ret() As Byte nBufferSize = WideCharToMultiByte(CP_UTF8, 0, StrPtr(s), Len(s), 0, 0, 0, 0) ReDim Ret(0 To nBufferSize - 1) WideCharToMultiByte CP_UTF8, 0, StrPtr(s), Len(s), VarPtr(Ret(0)), nBufferSize, 0, 0 LenByteUTF8 = UBound(Ret) + 1 End Function Function IsLengthle255byteOnUTF8(s As String) As Boolean ' test版であり、検証中です ' UTF-8に変換し、Byte配列に代入し、個数をカウントする ' 255より大きい場合はFalse ' この関数を使う場合、 ' https://qiita.com/Q11Q/items/a2d61545d9e5c4e15f22 ' VBEの設定に注意してください If Len(s) = 0 Then IsLengthle255byteOnUTF8 = False Exit Function End If Dim nBufferSize As Long Dim Ret() As Byte Dim cnt As Long nBufferSize = WideCharToMultiByte(CP_UTF8, 0, StrPtr(s), Len(s), 0, 0, 0, 0) ReDim Ret(0 To nBufferSize - 1) WideCharToMultiByte CP_UTF8, 0, StrPtr(s), Len(s), VarPtr(Ret(0)), nBufferSize, 0, 0 cnt = UBound(Ret) + 1 If cnt > 255 Then IsLengthle255byteOnUTF8 = False: Exit Function Else IsLengthle255byteOnUTF8 = True: Exit Function End Function前回のモジュールに追加する。
今回追加したのは
LenByteUTF8Function LengthUTF8(s As String) ' test版であり、検証中です ' UTF-8に変換し、Byte配列に代入し、個数をカウントする ' 255より大きい場合はFalse ' この関数を使う場合、 ' https://qiita.com/Q11Q/items/a2d61545d9e5c4e15f22 ' VBEの設定に注意してください If Len(s) = 0 Then LengthUTF8 = 0 Exit Function End If Dim nBufferSize As Long Dim Ret() As Byte Dim cnt As Long nBufferSize = WideCharToMultiByte(CP_UTF8, 0, StrPtr(s), Len(s), 0, 0, 0, 0) ReDim Ret(0 To nBufferSize - 1) WideCharToMultiByte CP_UTF8, 0, StrPtr(s), Len(s), VarPtr(Ret(0)), nBufferSize, 0, 0 cnt = UBound(Ret) + 1 LengthUTF8 = cnt End FunctionとIsLengthle255byteOnUTF8
である。Function IsLengthle255byteOnUTF8(s As String) As Boolean ' test版であり、検証中です ' UTF-8に変換し、Byte配列に代入し、個数をカウントする ' 255より大きい場合はFalse ' この関数を使う場合、 ' https://qiita.com/Q11Q/items/a2d61545d9e5c4e15f22 ' VBEの設定に注意してください If Len(s) = 0 Then IsLengthle255byteOnUTF8 = False Exit Function End If Dim nBufferSize As Long Dim Ret() As Byte Dim cnt As Long nBufferSize = WideCharToMultiByte(CP_UTF8, 0, StrPtr(s), Len(s), 0, 0, 0, 0) ReDim Ret(0 To nBufferSize - 1) WideCharToMultiByte CP_UTF8, 0, StrPtr(s), Len(s), VarPtr(Ret(0)), nBufferSize, 0, 0 cnt = UBound(Ret) + 1 If cnt > 255 Then IsLengthle255byteOnUTF8 = False: Exit Function Else IsLengthle255byteOnUTF8 = True: Exit Function End Function前回のtoUTF8からbyte単位のカウント方法が判る。
ReDim Ret(0 To nBufferSize - 1)
ここでバイト単位がカウントされている。
このまま出してもいいのかもしれないが、Win32APIの挙動がわからないので、確実に配列に代入する。
そしてUboundで取得した要素数に1を足す。
これも0ではなく Redimのときに1にしてよいのかもしれないが、この配列がWin32Apiに入るため、変えないほうがよいと判断した。これはWindowsのサーバーのディレクトリやファイルの長さではありません
社長のブログにあるようにUTF-8で半角で255字、255バイトと言われるのはWindowsではなくLinuxであり、Windowsのサーバーのファイルの長さはこれでは測ることができない。
サロゲートペアは4バイト
このベースでカウントするとサロゲートペアは4バイト、半角で4文字消費する。
全角のように見えても、42文字が限界になると考えられる。
検索してみると5バイトや6バイトがあるとかあるけどはねられるとか諸説が見つかる。
IBMの資料を見てもUTF-8は最大で4バイトとしている。
https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_11.5.0/com.ibm.db2.luw.admin.nls.doc/doc/c0004816.html
このため、最大が4バイトとしておく。そして4バイトの例がサロゲートペアということになる。バイトと文字数
今回の関数は文字列をUTF-8のバイト単位に換算している。それで全角も半角も関係なくコードに置き換えてその長さできまるようだ。
つまり容量としては255バイト、字数としては255字なので文中は使い分けている。Win32APIと長所
たしかにコード的には長くなるがADODBを参照設定しなくていい。
また、toUTF8はUTF-8のバイト配列に変換してしまうため、スピルなどがなければ使いどころがなかった。
しかし、それはExcelのWorksheet上でしか有効ではないため、Excelでしか使いづらい。
今回の関数は字数をバイト数に変えたり、255文字を判定するため、Excelだけではなく、Access,Word,PublisehrOutlookでも活用が可能である。
- 投稿日:2020-11-22T21:37:44+09:00
Linux まとめ
コマンド
; $pwd;ls
左のコマンドでエラーが起きても成功しても右のコマンドを実行する。
&& $ls prog/ruby && pwd
最初のコマンドが正常に終了した時だけ2番目のコマンド実行
|| $cat temp||echo "file not found"
最初のコマンドが正常に終了しなかった時だけ、2番目のコマンドが実行される。
() $(date;pwd;ls)>kekka.log
コマンドをまとめて実行
’’(シングルクォーテーション)
$echo $DATE
>8月31日
$echo '$DATE'
>$DATE
文字列として出力される。""(ダブルクォーテーション)
$echo $DATE
>8月31日
$echo "今日の日付は$DATEです"
>今日の日付は8月31日です。
''と同じ。$の変数の部分は変数として出力される。``(バッククォーテーション)
$echo"カレントディレクトリは'pwd'です。"
>カレントディレクトリは/home/lpicです。$echo"カレントディレクトリは$(pwd)'です。"
>カレントディレクトリは/home/lpicです。コマンド結果を出力できる。下の書き方の方がわかりやすいのでおすすめ。
less
キー操作 説明 スペースキー 下方向に1画面スクロール bキー 上方向に1画面スクロール / 下方向検索 ? 上方向検索 |(パイプ)
ls | wc -l
lsコマンドの実行結果をwcの標準入力に渡す。dmesg|less
カーネルメッセージをlessの標準入力に渡す。>(リダイレクト)
$ls -l > filelist
表示結果をfilelistにいれる。>>
$ls -l >> filelist
表示結果をfilelistの末尾に追加。<
$grep "lpic" result.txt
標準入力$cat > sample.txt <<EOF
EOFが入力されるまで、出力。2>
$find / -name "*.tmp" 2> error.log
エラー出力のみをファイルに保存。cat
cat file1 file2 > newfile
応用:file1 file2をnewfileに連続して書き込む
オプション 説明 -n 行番号をつけて表示 nl
テキストファイルに行番号をつけて表示。
tail
最終行から10行表示。
オプション 説明 -n 行数 指定された行数だけ表示 -f リアルタイム表示。表示中に追加されたら更新する。(ctrl+cで終了) tr
$cat /etc/hosts | tr 'a-z' 'A-Z'
ファイルの中の小文字を全て大文字に変換してcatsplit
$split -100 sample.txt s_sample.
sample.txt s_sample.aa s_sample.ab s_sample.ac
sample.txtを100行ごとに他のファイルに分ける。
(ファイル名はaa,ab,ac...末尾につく)ハッシュ
コマンド 説明 md5sum MD5によるハッシュ値を出力する sha1sum sha256sum sha512sum $sha1sum sample.txt
sample.txtファイルのSHA1ハッシュ値を表示grep
$grep -i ab sample.txt
$grep -v '^#' /etc/httpd/conf/httpd.conf
冒頭に#がつく行(コメントアウト)を省いて表示。(^:初めの一文字目を表す正規表現)
オプション 説明 -i 大文字小文字を区別せず検索 -v パターンがマッチしない行を表示 vi
入力モード
コマンド 説明 i カーソルの前にテキストを入力する a カーソルの後にテキストを入力する I 行頭の最初の文字にカーソルを移動し、その直前にテキストを入力する A 行末にカーソルを移動し、その直後にテキストを入力する o カレント行の下に空白行を挿入し、その行でテキストを入力する O カレント行の上に空白行を挿入し、その行でテキストを入力する コマンドモード
コマンド 説明 h 1文字左へ移動する l 1文字右へ移動する k 1行上へ移動する j 1行下へ移動する o 行の先頭へ移動する $ 行の末尾へ移動する H 画面の一番上の行頭へ移動する L 画面の一番下の行頭へ移動する gg ファイルの先頭行へ移動する G ファイルの最終行へ移動する nG ファイルのn行目に移動する :n ファイルのn行目に移動する 5hで5文字左に移動
コマンド 説明 :q ファイルへ保存せずに終了する :q! 編集中の内容を保存せずに終了する :wq 編集中の内容を保存して終了 :w 編集中の内容でファイルを上書き保存する :e! 最後に保存した内容に復帰する :! コマンド viを終了せずにシェルコマンドを実行する :r! コマンド シェルコマンドの実行結果を挿入する :!ls でviを動作させたまま、lsコマンドを実行できる。
viの編集コマンド
コマンド 説明 dd カレント行を削除 dw カーソル一から次の単語までを削除する yy カレント行をバッファにコピーする :w 編集中の内容でファイルを上書き保存する p カレント行の下にバッファの内容を貼り付ける P カレント行の上にバッファの内容を貼り付ける x カーソル位置の文字を削除(delete) X カーソル位置の手前の文字を削除(backspace) 5dd でカーソル位置から5行削除。
viの検索コマンド
コマンド 説明 / カーソル位置から後ろ方向に向かって検索 ? カーソル位置から後ろ方向に向かって検索 n 次を検索する N 次を検索する(逆方向) :noh 候補のハイライト表示を解除する :%s/A/B/ 最初に見つかった文字列Aを文字列Bに置換する :%s/A/B/g 全ての文字列Aを文字列Bに置換する
コマンド 説明 :set nu 行番号を表示する :set nonu 行番号をh非表示する :set ts=タブ幅 タブ幅を数値で指定する ファイル管理
gzip
コマンド 説明 -d 圧縮ファイルを展開する -c 標準出力へ出力 -r ディレクトリ内のファイル全て圧縮する $gzip datafile
ファイルを圧縮$gzip -r sampled
sampledディレクトリ内にある全てのファイルを個々に圧縮$gzip -c datafile >datafile.gz
圧縮前のフォルダも残し圧縮$bzip2 datafile
bzipはgzipよりも時間がかかるが圧縮効率は高い。
(解凍は オプション -dをつける)$xz datafile
xzはbzipよりも時間がかかるが圧縮効率は高い。
(解凍は オプション -dをつける)zcat,bzcat,xzcat
$zcat sample.gz
圧縮されたテキストファイルを解凍せずに確認する。tar
ファイルやディレクトリを1つのアーカイブファイルにまとめたり、それを展開できる。
zオプションでgzip圧縮と同じ。
コマンド 説明 -c アーカイブを作成する -x アーカイブからファイルを取り出す -t アーカイブの内容を確認する -f ファイル名 アーカイブファイル名を指定する -z gzip 圧縮/展開 -j bzip2 圧縮/展開 -J xz 圧縮/展開 -v 詳細な情報を表示する -u アーカイブ内にある同名のファイルより新しいものだけを追加する -r アーカイブにファイルを追加する -N 指定した日付より新しいデータのみを対象とする -M 複数デバイスへの分割 -delete アーカイブからファイルを削除する tar cvf /dev/st0 /home
/homeのアーカイブファイルを /dev/st0に作成tar xvzf software.tar.gz
アーカイブファイルをカレントディレクトリに展開。tar tf /dev/sdb1
/dev/sb1にあるアーカイブの内容を表示する。tar xvf /dev/sdb1 var/log/secure
/varcpio
$ls | cpio -o >/tmp/backup
カレントディレクトリを/tmp/backupファイルとしてバックアップ。dd
$dd if=/dev/sdb of=/dev/sdc
/dev/sdbに接続されたディスクの内容をそのまま/dev/sdbに出力。ddコマンドは、ハードディスクやCD-ROMなどのデバイスの内容をそのまま扱える。
cpコマンドは、ファイルをコピーするだけ。
コマンド 説明 -if 入力側ファイルを指定する -of 出力側ファイルを指定する chmod
オプション 説明 -R 指定したディレクトリ以下にある全ファイルのアクセス権を変更する
対象 説明 u 所有者 g グループ o その他ユーザー a 全てのユーザー
操作 説明 + 権限を追加する - 権限を削除する = 権限を指定する
許可の種別 説明 r 読み取り許可 w 書き込み許可 x 実行許可 s SUID or SGID t スティッキービット $chmod go+w samplefile
グループとその他ユーザーに書き込み権限を与える$chmod o-rw samplefile
その他ユーザーから書き込み実行権限をなくす$chmod 644 samplefile
644に変更SUID,SGID
SUID ファイルの所有者の権限で実行可能
chmod u+s samplefile
SGID グループのアクセス権が適用される。
スティッキービット
書き込み権限はあっても、自分以外のユーザーが所有するファイルを削除できない。
chmod o+t sampledir
umask
デフォルトのアクセス権が決められている。
$umask
0002ディレクトリは777からファイルは666からumaskを引いた権限がデフォルト
d→775 file→664
chown
オプション 説明 -R 指定したディレクトリとその中にある全ファイルの所有者を変更する ハードリンク
それぞれのファイルで同一の実体を参照する。
$ln file.original file.link_hardシンボリックリンク
リンク下の場所を示す。(ショートカット)
$ln -s file.original file.link_hardls -l
作成したリンクを確認。シンボリックリンクのコピーにはdをつける。
cp -d file.link_sym file.link3
付けないとリンク元のファイルがコピーされる。
cp file.link_sym file.link2top
プロセスの監視
Qで終了バックグラウンドジョブの実行
updatedb &
&を付けることでバックグラウンドで処理を実行できる。jobs
jobsコマンドで実行中のジョブを確認できる。長時間にわたって席を外す場合などで実行し続けげ欲しい。
ログアウトしても実行していて欲しい場合。
nohubを付ける。
$nohup updatedb &現在実行しているジョブをバックグラウンドで行いたい場合。
ctrl + zで一時停止 → bg 1
(1はジョブの番号 jobsでわかる)
バックグラウンドをフォアグラウンドに変えたいときはfgfree
メモリの空き状況
オプション 説明 -m MB単位で表示する -s 秒 指定した間隔で表示し続ける uptime
平均負荷など
uname
OSの確認
uname -a
詳細表示watch
watch -n 10 uptime
10秒ごとにuptimeを実行。nice
コマンド実行時の優先度指定。
$nice -n -10 updatedbデバイス管理ファイル管理
find
$find /root -name "*.txt"
ファイル名で検索
検索式 説明 -name ファイル名 ファイル名で検索する -atime 日時 最終アクセス時刻で検索する -mtime 日時 最終更新時刻で検索する -perm アクセス権 アクセス権で検索する -size サイズ ファイルサイズで検索する -type ファイルの種類 ファイルの種類で検索するf:ファイル l:シンボリック d:ディレクトリ -user ユーザー名 ファイルの所有者で検索する マッチしたファイルを表示する -exec コマンド || ¥; マッチしたファイルに対してコマンドを実行 -ok コマンド || ¥; マッチしたファイルに対してコマンドを実行(確認あり) $find /data -type f -mtime -1
過去1日以内に更新されたファイルを検索$find /usr/bin -type f -perm -u+s
/usr/binディレクトリ以下からSUIDが設定されたファイルを検索。$find /tmp -user student
所有者がstudentであるファイルディレクトリを検索。$find -atime +30 -exec rm {}¥;
30日を超える日数の間アクセスされていないファイルを検索し、削除。シェルとシェルスクリプト
エイリアス
$alias ls='ls -l'
コマンドに別名をつけることができる。
$alias lsless='ls -l|less'$unalias lsless
設定されているエイリアスを解除関数
$function lslink(){ls -l|grep '^l';}
シンボリックリンク (lから始まる)のみを表示するlslink関数$function lslink(){ls -l $1 | grep '^1';}
$1で引数。引数にディレクトリなどを入れれる。$declare -f lslink
定義されている関数のみを表示。unset lslink
lslink関数を削除。bashの設定ファイル
ファイル 説明 /etc/profile ログイン時に実行され、全ユーザーから参照される /etc/bash.basic bash起動時に実行され、全ユーザーから参照される /etc/bashrc ~/.bashrcから参照される bash起動時から参照。 ~/.bash_profile ログイン時に実行される ~/.bash_login ~/.bash_profileがない場合、ログイン時に実行される ~/.profile ~/.bash_profileも~/.bash_loginもない場合、ログイン時に実行 ~/.bashrc bash起動時に実行される ~/.bash_logout ログアウト時に実行される シェルスクリプト
実行(読み取り権限必要)
$bash lsld$source lsld
$. lsld
(実行権限必要)
chmod a+x lsld
$./lsls
そのままファイル名で実行される。
変数名 説明 $0 シェルスクリプトファイル名(フルパス) $1 1番目の引数 $2 2番目の引数。以下$3$4$5 $# 引数の数。 $@ 全ての引数(スペース区切り) $* 全ての引数(区切りは環境変数IFSで指定されたもの) 実行結果の戻り値
正常終了→0
異常終了→0以外$echo $?
2戻り値は$?に代入される。
ファイルのチェック
testコマンド
条件式 実行結果 ファイル形式のテスト -f ファイル (ディレクトリなどを除く)ファイルがあれば真 -d ディレクトリ ディレクトリがあれば真 -r ファイル ファイルが存在し、かつ読み込み可能であれば真 -w ファイル ファイルが存在し、かつ書き込み可能であれば真 -x ファイル ファイルが存在し、かつ実行可能であれば真 -s ファイル サイズが0より大きいファイルがあれば真 -L ファイル シンボリックリンクであるファイルがあれば真 ファイル特性のテスト -e ファイル ファイルがあれば真 ファイル1 -nt ファイル2 ファイル1がファイル2より修正時刻が新ければ真 ファイル1 -ot ファイル2 ファイル1がファイル2より修正時刻が古ければ真 数値のテスト 数値1 -eq 数値2 数値1と数値2が等しければ真 数値1 -ge 数値2 数値1が数値2より大きい、もしくは等しければ真 数値1 -gt 数値2 数値1が数値2より大きければ真 数値1 -le 数値2 数値1が数値2より小さい、もしくは等しければ真 数値1 -lt 数値2 数値1が数値2より小さいもしくは等しければ真 数値1 -ne 数値2 数値1と数値2が等しくなければ真 文字列のテスト -n 文字列 文字列の長さが0より大きければ真 -z 文字列 文字列の長さが0であれば真 文字列1=文字列2 2つの文字列が等しければ真 文字列1!=文字列2 2つの文字列が等しくなければ真 テストの論理結合 !条件 条件が偽であれば真 条件1 -a 条件2 両方の条件式が真であれば真(and) 条件1 -o 条件2 いずれかの条件式が真であれば真(or) 条件分岐
if 条件式
then
実行文1
else
実行文2
fiCase
case $1 in
1)echo "January";;
2)echo "February";;
esacread
名前を標準入力から聞くことができる。
echo -n "Who are you?:"
read username ←ここでユーザーに聞いて
echo "Hello,$username!" ←ここで使うシェルスクリプトの1行目
#!/bin/bash管理タスク
ユーザーアカウント設定されているファイル
/etc/passwdグループ
/etc/groupuseradd
useradd -c "Linux User" -d /home/linux -s /bin/bash linuxuser
オプション 実行結果 -c コメント コメントフィールドを指定 -d ディレクトリ ホームディレクトリを指定 -s パス デフォルトシェルを指定 ジョブスケジューリング
cron
crontab
/var/spool/cron ディレクトリ以下に置かれる。
オプション 実行結果 -e crontabを編集(直接viなどで開いてはいけない) -l 内容表示 -r ファイル削除 -i 削除時に確認する -u ユーザー名 ユーザー名を指定してcrontabファイルを編集(rootユーザーのみ) 書式
分 時 日 月 曜日 コマンド
フィールド 実行結果 曜日 0-7までの整数(0,7:日曜〜6土曜) 15 23 * * * /usr/local/bin/backup
(毎日23:15に起動)0 9,12 * * 1 /usr/local/bin/syscheck
(月曜の09:00と12:00に起動)0 */2 * * * /usr/local/bin/syscheck
(2時間ごとに起動)at
一回限りのスケジューリング
$at 5:00 tomorrow
at>/usr/local/sbin/backup
at>^D ←ctrl+Dキーを入力で終了。systemd
何らかのイベントから一定時間後に発動などができる。
メール
mail[-s題名][宛先メールアドレスorユーザー名]
mail -s samplemail student
Hello!Student! ←本文
.
EOT
受信メールを確認ネットワークの基礎
ping
オプション 実行結果 -c 回数 指定した回数だけパケット送信 -i 間隔 指定した間隔(秒)ごとにポケット送信 traceroute
指定されたホストまでパケットが伝わる経路を表示。
hostname
現在のホスト名を表示。
ホスト名を指定した場合、ホスト名を変更。
netstat
ネットワークの様々な情報を表示。
開いているポートの確認など。nc
ネットワーク上のcatコマンド
$nc -l -p 12345 -o listen.log
12345番ポートで待ち受けし、受け取ったデータをlisten.logファイルに出力。$nc centos7.example.com 12345<data.txt
ホストの12345ポートに対し、data.txtファイルの内容を出力。ifconfig
ipアドレスの確認。
DNSの設定ファイル
/etc/resolv.conf
/etc/nsswitch.conf
hostsを優先するかDNSサーバーを優先するかの順序を選択。host
ホストのipがわかる。ipのホストがわかる。
セキュリティ
nmap
$nmap www.example.net
開いているポート番号とサービス名(ssh,http)が確認できる。SUIDが設定されているファイルを確認する方法。
定期的に確認を行うべし。
#find / -perm -u+s -ls一般ユーザーのログインを停止する
#touch /etc/nologin
nologinファイルを作成しておくことで、ルート以外のログイン以外は禁止される。scp
scp コピー元ファイル名 [ユーザー名@] コピー先ホスト:[コピー先ファイル名]
scp /etc/hosts sv3.example.jp:/tmp
ローカルホストの/etx/hostsをリモートホストsv3.example.jpの/tmp以下にコピー。scp [ユーザー名@]コピー元ホスト:コピー元ファイル名 コピー先ファイル名
$scp sv3.example.jp:/etc/hosts .
リモートホストsv3.example.jpの/etc/hostsをカレントディレクトリにコピー。$scp data.txt fred@sv3.example.jp:
リモートホストsv3.example.jpのfredユーザーのホームディレクトリにローカルホストのdata.txtファイルをコピー
- 投稿日:2020-11-22T20:46:23+09:00
小プロセスを含めたkill
概要
小プロセスを含め、killをするためのツールです。python用です。
(pythonのプロセスで縛りを掛けています。)
検証はlinuxのみしてあります。使い方は、
そのまま実行すると、小プロセスを持つ親プロセスの一覧が表示されるので、
(例としてproc_01.py proc_02.pyの小プロセスを持つプログラムが実行中とします。)$ python terminate_children_process.py python 関連の小プロセスを持つprocess一覧 コマンドラインにPIDを指定すると、小プロセスを含めてterminate します。 {'pid': 26727, 'cmdline': ['python', 'proc_01.py']} {'pid': 26747, 'cmdline': ['python', 'proc_02.py']}終了させたいpidを指定し再び実行します。
$ python terminate_children_process.py 26747 terminate 子プロセス 26849 terminate 子プロセス 26850 terminate 子プロセス 26851 terminate 親プロセス 26747ソース(terminate_children_process.py)
#terminate_children_process.py import sys import psutil if len(sys.argv)==1: #python 関連の小プロセスを持つprocessの表示 print("python 関連の小プロセスを持つprocess一覧") print("コマンドラインにPIDを指定すると、小プロセスを含めてterminate します。") PROCNAME = "python" for proc in psutil.process_iter([ "pid" , 'cmdline' ]): if proc.name()[:len(PROCNAME)] == PROCNAME: p = psutil.Process(proc.pid) if len(p.children()) >0: print(proc.info) else: #指定したPIDとその小プロセスを含めてterminate target_pid=int(sys.argv[1]) p = psutil.Process(target_pid) #子のterminate pid_list=[pc.pid for pc in p.children(recursive=True)] for pid in pid_list: psutil.Process(pid).terminate () print("terminate 子プロセス {}" .format(pid)) #親のterminate p.terminate () print("terminate 親プロセス {}" .format(target_pid))参考
- 投稿日:2020-11-22T19:13:19+09:00
【Linux】ファイル検索
- 投稿日:2020-11-22T17:14:41+09:00
JVNVU#97690270 (RPMB脆弱性)を簡単に確認してみた
この記事はLinux Advent Calendar 2020の5日目です。
TL;DR
- Replay Protected Memory Block (RPMB) プロトコルでは、共通鍵を利用して、HostとDevice間で処理するデータについて検証する手段。
- ところが、今回指摘した脆弱性を使うと 「Hostには失敗と応答されたのに、Deviceではデータが書かれている」「Hostには成功と応答されたのに、Deviceはデータを書いていない」 というケースが作れそう。
- Linux Kernel本体にはRPMBへアクセスするための直接的なロックは存在してない。mmc-utils上でにコマンドラインから呼び出すコードがある。
はじめに
- JVN ( Japan Vulnerability Notes ) では、セキュリティレポートが出ています。
- その中でプロトコルレベルっぽい指摘があった。
- この指摘について、Linux中心に確認していく(軽く)。
想定される影響
RPMB プロトコルを利用するシステムに直接アクセス可能な第三者によって、次のような影響を受ける可能性があります。
・RPMB 領域への書込みが成功したにも関わらず失敗したようにホストに誤認識させる
・RPMB 領域にホストの意図とは異なる内容を書き込んだにも関わらず、意図通りの内容を書き込んだとホストに誤認識させるこのあたりをもうちょっと読み解いていく!
そもそもReplay Attackとは?
雑に説明すると、こんな感じ。詳細は、Wikipediaの反射攻撃 を参考ください。
- 悪意ある人間が認証情報ごと丸ごとコピーすると、正規要求なのか不正要求なのかわからなくなる。
- 下記の例だと「社長」の判子がある要求には、「経理」は正規要求だと認識して、現金を手渡す。
- では、社長の作った書類を悪い人が盗聴・複製して、コピーを経理に渡したら?
- 経理の人は本物と偽物の見分けがつかないので、現金を支払ってしまう。
- 社長が見ると「あれ?これ・・・なんで2回10万円?」と悩む。
Replay Protected Memory Block (RPMB) プロトコルとは?
Replay Protected Memory Block (RPMB) protocol does not adequately defend against replay attacksからリンクが張られていた、Western Digital社のe.MMC Security Methods を基に確認してみる。
- HostとDeviceでそれぞれ暗号鍵情報を分けて持っている。
- Read OnlyなCounterがあることで、Replay Attackをすると必ずMACがズレて失敗する。
Western Digital社のwhite-paper-emmc-security.pdfから引用。
今回の攻撃は?
wdc-20008-replay-attack-vulnerabilities-rpmb-protocol-applications にリンクが張られているwhite-paper-replay-protected-memory-block-protocol-vulernabilities.pdf 詳細が記載されているので、これを紹介したい。
Case 1 : データ書いているけど、書かなかったことにする
振る舞い
- (1) Hostは、REQ( カウンタCt, アドレスAdr, MAC Mを、Device) を送信。
- (2) 敵(adversary) が、Host->Device間の通信に割り込む!!
- 敵は、失敗するようにMAC値を書き換えたREQ* を Deviceに送信、
- (3) Deviceは検証をするけど、MAC値不正で失敗をHostへ返却。
- 失敗しているので、Device側のカウンタ値は更新されない。
- Hostは失敗が通知されたので「失敗した」と認識する。
- (4) 敵は、REQをDeviceに送信。
- (5) DeviceはREQを検証し、カウンタCtもMAC Mも正しいので成功と判断してデータを書き換える。
結果
- Host 「え?REQを送ってみたけど、失敗したよ。データは書き換わってないはずだよ」
- Device「REQ*は失敗したけど、REQは成功したよ。データは書き換わっているよ!」
という感じで、認識の相違が発生する!!!怖いですねー
Case 2 : データ書いていないけど、書いたことにする
振る舞い
- (1) Hostは、REQ1( Ct, Data1, Adr, M1) を送信。
- 敵(adversary) が、Host->Device間の通信に割り込む!!
- 敵は、REQ1を記録しておく。
- (2) 状態の喪失:例えば電源切断
- (3) 復帰:例えば再起動
- (4) Hostは、REQ2( Ct, Data2, Adr, M1) を送信。
- 敵(adversary) が、Host->Device間の通信に割り込む!!
- (5) 敵は、REQ2ではなく、REQ1をDeviceへ送信!
- (6) DeviceはREQ1を検証し、カウンタCtもMAC Mも正しいので成功と判断してデータを書き換える。成功をHostへ返却。
結果
- Device「REQ1の要求受けたから、そのData1でちゃんと書き換えましたよ!成功しました!」
- Host 「REQ1の応答がなかったような…。。。 でも、最後に送信したREQ2に対しては成功が帰ってきたから、Data2で書き換えられているはずです!」
あらららら……
Linux KernelのRPMB実装を確認してみよう!
からサポートが始まっている………… と、思うじゃろ?
https://lkml.org/lkml/2016/11/7/674
このスレッドから始まる議論では、この修正は含まれなかった。
その結果、RPMBへアクセスするためのインタフェイスは存在していない、と。えええ、じゃあどうやってアクセスするのかー、っというところで、見るべきポイントは「mmc-utils」です。
mmc-utils
https://git.kernel.org/ にちゃーんとリンクが張られている。
https://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc-utils.git/
ここで、データを書き込むコマンド、do_rpbm_write_block()に閉じて、その振る舞いを確認していく!と思ったけど、大体話は上で書いたものとそう大差さないので、最後にAppendixとしてまとめておきます。
予備知識
mmc rpmb write-key </path/to/mmcblkXrpmb> </path/to/key>
- HostからDeviceへ鍵情報を書き込める。
mmc rpmb read-counter </path/to/mmcblkXrpmb>
- HostはDeviceからカウンタ情報を読み出せる。
mmc rpmb read-block </path/to/mmcblkXrpmb> <address> <blocks count> </path/to/output_file> [/path/to/key]
- HostはDeviceから、指定した鍵情報keyを利用して、指定したアドレスaddressからblock_countの数だけの内容を読み取り、output_fileへ出力できる。
mmc rpmb write-block </path/to/mmcblkXrpmb> <address> </path/to/input_file> </path/to/key>
- HostはDeviceへ、指定した鍵情報keyを利用して、指定したアドレスaddressへinput_fileの内容を書き出せる。
考察
- mmc-utilsの実装コードを見ていると、確かにHost/Device間でカウンター値の連続性とかチェックが無い。
- TCPのシーケンス番号もないから、確かにCase2のようにその応答が今回のコマンド要求に対する応答かどうかとかもわからないなあ…
- つまり、プロトコルレベルでの設計で、問題があったんだなあと…。
- RPMBに重要な情報を保持するとわかっていると、ここを集中して狙われそう。確かにこれはまずい…。
まとめ (再掲)
お忙しい中、ここまで読んでいただき、ご精読頂き、ありがとうございました!!
以下のようにまとめます。
- Replay Protected Memory Block (RPMB) プロトコルでは、共通鍵を利用して、HostとDevice間で処理するデータについて検証する手段。
- ところが、今回指摘した脆弱性を使うと「Hostには失敗と応答されたのに、Deviceではデータが書かれている」「Hostには成功と応答されたのに、Deviceはデータを書いていない」というケースが作れそう。
- Linux Kernel本体にはRPMBへアクセスするための直接的なロックは存在してない。mmc-utils上でにコマンドラインから呼び出すコードがある。
補足…
- 本脆弱性の具体的なユースケースや対策方法は、white-paper-replay-protected-memory-block-protocol-vulernabilities.pdf に記載がある。
- さすがに全部丸ごとコピーするのは違う、ということで、より詳細に興味ある方はそちらを確認いただければと思います。
Appendix (mmc-utilsの実装確認)
このコードを簡単に読んでいく。
各種変数定義
書き込むREQを格納する、
struct rpbm_frame frame_in
を定義する。mmc_cmds.cint do_rpmb_write_block(int nargs, char **argv) { int ret, dev_fd, key_fd, data_fd; unsigned char key[32]; uint16_t addr; unsigned int cnt; struct rpmb_frame frame_in = { .req_resp = htobe16(MMC_RPMB_WRITE), .block_count = htobe16(1) }, frame_out;/dev/mmcblkXrpmbを開く。
dev_idは、
/dev/mmcblkXrpmb
のfilr descriptor。mmc_cmds.cif (nargs != 5) { fprintf(stderr, "Usage: mmc rpmb write-block </path/to/mmcblkXrpmb> <address> </path/to/input_file> </path/to/key>\n"); exit(1); } dev_fd = open(argv[1], O_RDWR); if (dev_fd < 0) { perror("device open"); exit(1); }カウンターの値をdeviceから読み出す
mmc_cmds.cret = rpmb_read_counter(dev_fd, &cnt); /* Check RPMB response */ if (ret != 0) { printf("RPMB read counter operation failed, retcode 0x%04x\n", ret); exit(1); } frame_in.write_counter = htobe32(cnt);アドレス情報をセットする
mmc_cmds.c/* Get block address */ errno = 0; addr = strtol(argv[2], NULL, 0); if (errno) { perror("incorrect address"); exit(1); } frame_in.addr = htobe16(addr);データや鍵情報をファイル/標準入力から読み出す
mmc_cmds.c/* Read 256b data */ if (0 == strcmp(argv[3], "-")) data_fd = STDIN_FILENO; else { data_fd = open(argv[3], O_RDONLY); if (data_fd < 0) { perror("can't open input file"); exit(1); } } ret = DO_IO(read, data_fd, frame_in.data, sizeof(frame_in.data)); if (ret < 0) { perror("read the data"); exit(1); } else if (ret != sizeof(frame_in.data)) { printf("Data must be %lu bytes length, but we read only %d, exit\n", (unsigned long)sizeof(frame_in.data), ret); exit(1); } /* Read the auth key */ if (0 == strcmp(argv[4], "-")) key_fd = STDIN_FILENO; else { key_fd = open(argv[4], O_RDONLY); if (key_fd < 0) { perror("can't open key file"); exit(1); } } ret = DO_IO(read, key_fd, key, sizeof(key)); if (ret < 0) { perror("read the key"); exit(1); } else if (ret != sizeof(key)) { printf("Auth key must be %lu bytes length, but we read only %d, exit\n", (unsigned long)sizeof(key), ret); exit(1); }これまでの書き込みデータの内容から、HMACの値を計算する
mmc_cmds.c/* Calculate HMAC SHA256 */ hmac_sha256( key, sizeof(key), frame_in.data, sizeof(frame_in) - offsetof(struct rpmb_frame, data), frame_in.key_mac, sizeof(frame_in.key_mac));REQを送信するためのRPMB 処理を実行し、結果を確認する
mmc_cmds.c/* Execute RPMB op */ ret = do_rpmb_op(dev_fd, &frame_in, &frame_out, 1); if (ret != 0) { perror("RPMB ioctl failed"); exit(1); } /* Check RPMB response */ if (frame_out.result != 0) { printf("RPMB operation failed, retcode 0x%04x\n", be16toh(frame_out.result)); exit(1); }後始末
mmc_cmds.cclose(dev_fd); if (data_fd != STDIN_FILENO) close(data_fd); if (key_fd != STDIN_FILENO) close(key_fd); return ret; }
- 投稿日:2020-11-22T15:06:12+09:00
スタンドアローン状態のUbuntuにネットワークドライバをインストールする方法
背景
- Among usっていうゲームやりたくてUbuntuのProtonの設定をいじってました。
- GPUのドライバがインストールできてなかったことに気づきました。
- 適当な以下のコマンド打ってみました。
sudo ubuntu-drivers autoinstallネットワークとサウンドが死にました。
もともと、マザーボードのEthernetソケットはドライバインストールが面倒だったので、USB-NICを使ってました。USB-NICは普通に認識できてたのですが、上記操作でそれすら使えなくなりました。なんか他にやっちゃったのか?
ま、とりあえず回復しましょう。
この際なので、マザーボードのEthernetソケット用に設定しましょう。状況調査
以下で現在のカーネルバージョンを調べました。
$ uname -r 5.4.0-54-generic次に、ネットワークチップの種類を調べました。
$ lspci | grep Ether 06:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8125 2.5GbE Controller (rev 05)realtek RTL8125ですね。
所定の場所にドライバが存在するか調べました。すでに調べたカーネルVerのディレクトリ配下です。$ls /lib/modules/5.4.0-54-generic/kernel/drivers/net/ethernet/realtek/ 8139cp.ko 8139too.koRTL8125は無いですね。
こいつを作る必要があります。
RTL8125ドライバ生成用ファイル群は以下Realtek公式ページで取得できます。
https://www.realtek.com/en/component/zoo/category/network-interface-controllers-10-100-1000m-gigabit-ethernet-pci-express-softwareMakefile、autorun.shの中身からドライバの生成にはmake、gccコマンドが必要だとわかるのですが、残念ながらそれらはインストールされていません。ネットも使えないのでapt installもできません。なので別のサブPCでドライバ生成し、それをUSBドライブで持ってくることとします。
環境
メインPC:
詳細 備考 OS Ubuntu 20.04 CPU AMD Ryzen 9 3900XT network chip Realtek RTL8125 サブPC:
詳細 備考 OS Ubuntu 18.04 CPU Intel(R) Core(TM) i5-8400 サブPC作業手順
VirtualBox上で、Ubuntu20.04をインストールし、
uname -r
でカーネルVerがメインPCと同一であることを確認。1回目は違ったので、upgradeしたら同一になりました。他の記事など参考にしてください。これとか先述の公式ファイル群をVirtualBox上でダウンロードし、そのフォルダにて
./autorun.sh
を実行します。おそらくなにか足りない旨の表示がありますが、3の手順でドライバが生成されてれば問題ないです。VirutualBox上で以下を実行し、
r8125.ko
があることを確認。$ ls /lib/modules/5.4.0-54-generic/kernel/drivers/net/ethernet/realtek/ 8139cp.ko 8139too.ko atp.ko r8125.ko r8169.ko4.VirutualBox上からサブPCに
r8125.ko
を移動。これはscpや共有フォルダなどで移動してください。5.USBドライブを使って
r8125.ko
をサブPCからメインPCの以下フォルダに移動。/lib/modules/5.4.0-54-generic/kernel/drivers/net/ethernet/realtek/メインPC作業手順
- 以下コマンドで一時的にドライバとして適用。
$ sudo insmod /lib/modules/5.4.0-54-generic/kernel/drivers/net/ethernet/realtek/r8125.ko2.数秒後、ネットワークが復活していることを確認。
3.確認できたら、再起動後も有効化されるように以下コマンドを打つ。
sudo depmod -a以上。
(おまけ)サウンド復活方法。
設定の音声のOutputDeviceにて、Dummy Outputのみが出力されている状態でした。
以下コマンドを打ってみました。inxiはaptでインストールしました。$ inxi -SMA System: Host: ueda-System-Product-Name Kernel: 5.4.0-54-generic x86_64 bits: 64 Desktop: Gnome 3.36.4 Distro: Ubuntu 20.04.1 LTS (Focal Fossa) Machine: Type: Desktop Mobo: ASRock model: B550M Steel Legend serial: <superuser/root required> BIOS: American Megatrends v: P1.10 date: 06/11/2020 Audio: Device-1: NVIDIA GP107GL High Definition Audio driver: N/A Device-2: AMD Starship/Matisse HD Audio driver: N/A Sound Server: ALSA v: k5.4.0-54-genericAudioのdriverがN/Aになってます。
このdriverは以下コマンド実行でインストールされました。sudo apt install linux-modules-extra-`uname -r`もう一度見てみます。
$ inxi -SMA System: Host: ueda-System-Product-Name Kernel: 5.4.0-54-generic x86_64 bits: 64 Desktop: Gnome 3.36.4 Distro: Ubuntu 20.04.1 LTS (Focal Fossa) Machine: Type: Desktop Mobo: ASRock model: B550M Steel Legend serial: <superuser/root required> BIOS: American Megatrends v: P1.10 date: 06/11/2020 Audio: Device-1: NVIDIA GP107GL High Definition Audio driver: snd_hda_intel Device-2: AMD Starship/Matisse HD Audio driver: snd_hda_intel Sound Server: ALSA v: k5.4.0-54-genericdriverがsnd_hda_intelになって、音も出るようになりました。
あとがき
7年ほどUbuntu縛り生活をしてきて、ネット断絶は良く発生してました。その度毎にOS再インストールなどのダサい回避策を行ってきていましたが、上記対応が出来たことでUbuntistとしてレベルアップした気がします。
今回はVirtualBoxでクロスコンパイル的にドライバを生成しましたが、makeの引数指定でスマートに生成出来たかもしれませんね。作業中調べてもなかなかヒットしなかったのでその方法は諦めました。詳しい人いたら教えてください。make,gccはOSインストール直後にやっておくべきですね。そうしたら、メインPCでコンパイルすれば良いだけの話になってたので。
- 投稿日:2020-11-22T01:16:27+09:00
Docker Desktop for WindowsをLinux(WSL)で操作
概要
WindowsにインストールしたDocker DesktopをWindowsにインストールしたLinux ディストリビューション(Ubuntu)で利用するためのセットアップ手順をメモ
さっくりまとめると、
なんらかのLinux ディストリビューションをインストールしたら
Docker Desktop の設定で WSL の統合を有効化するだけLinux ディストリビューション(Ubuntu)のインストール
基本以下を見ればOK
Windows 10 用 Windows Subsystem for Linux のインストール ガイド手順4までは、すでにDocker Desktopのセットアップを行っていれば、その際に実施済みのはず
手順 5 - WSL 2を既定のバージョンとして設定する
PowerShellでコマンド実行
wsl --set-default-version 2
メモ:WSL1とWSL2の違いについて1
手順 6 - 選択した Linux ディストリビューションをインストールする
今回はUbuntu 20.04 LTSをインストール
Ubuntuを起動
初回起動時はusernameとpasswordを聞かれるので、任意の名前とパスワードを入力すればそのまま登録される
新しい Linux ディストリビューションのユーザー アカウントとパスワードを作成するパッケージの更新とアップグレード
とりあえず、お約束
sudo apt update && sudo apt upgrade
dockerコマンド打ったら通らない、、、
満を持してWindows上のLinuxからdockerコマンド実行したが、期待した動きではないような、、
$ docker --version The command 'docker' could not be found in this WSL 2 distro. We recommend to activate the WSL integration in Docker Desktop settings. See https://docs.docker.com/docker-for-windows/wsl/ for details.Docker Desktopの設定をしてねという事らしい
Docker Desktop の設定で WSL の統合を有効化
DockerのSettings > Resources > WSL INTEGRATION でインストールしたLinuxディストリビューションへの統合を有効化
アプリを再起動
統合を有効化したら、Ubuntuアプリを再起動して改めてdockerコマンド実行したらdockerコマンド実行OK
$ docker --version Docker version 19.03.13, build 4484c46d9dこれで、晴れてWindows上のDockerをWindows上のLinuxから操作できる
WSL1とWSL2の違いについて WSL 1 と WSL 2 の比較の機能比較によるとWSL2は完全なLinuxカーネルとシステムコールの完全な互換性があり、WSL1と比較してzipファイルの展開が最大20倍早いとのこと、WindowsとLinux間でファイルのやり取りをする必要がある場合WSL1を利用するとよい場合もある模様 ↩