凡例 最もよく見る記述
sock = socket(AF_UNIX, SOCK_STREAM, 0);
AF_UNIX
: プロセス間通信用ソケット。他にはAF_INET
/ AF_VSOCK
などが入る。SOCK_STREAM
: データ境界の概念がないストリームはコレ。そうでなければSOCK_SEQPACKET
。0
: 9割方使わないsock
: 失敗すると-1でerrnoを設定。ret = bind(sock, (const struct sockaddr *) &addr, sizeof(addr));
sock
: socket
の返したもの。addr
: sockaddr_un
構造体を指定。#include <sys/un.h>
必要。sizeof(addr)
: サイズ。ret
: 成功で0、失敗で-1struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, path);
unlink(path);
if (bind(listenfd, (const struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("bind");
return -1;
}
構造体はこんな感じである。
ret = listen(sock, 10);
sock
: socket
が返してbind()
済みのもの。10
: backlogの数。accept
せずにためておける接続数。fd = accept(sock, NULL, NULL);
sock
: socket
が返してbind()
/ listen()
済みのもの。NULL
×2 : 1個目はaddr, 2個目はsizeを示す、クライアントが設定するsockaddr
構造体。見る必要がなければ両方NULL
。fd
: クライアントのfd
。失敗は-1でerrno設定。ret = recv(fd, buf, sizeof(buf), 0);
fd
: accept()
が返却のもの。buf
/ sizeof(buf)
: 受信バッファ。MSG_DONTWAIT
/ MSG_WAITALL
などを指定。ret
: 受信したバイト数。負値はエラー、0はクライアントが切断されたことを意味する。ret = send(fd, buf, len, 0);
fd
: accept()
が返却のもの。buf
/ len
: 送信バッファ。MSG_DONTWAIT
などを指定。ret
: 成功0、失敗-1。errno == ECONNRESET
はクライアントが切断されたことを意味する。前提
fork() /
pthread_create()による並列実行か
poll()`による多重化が必要です。accept()
)際は上記が必要です。チェック項目
というような背景からソケットプログラミング(特にサーバ)では多重化とマルチスレッドが必須となりどっちをやった場合でも抜け漏れが生じやすいです。...
]]>-serial mon:stdio
を指定して仮想マシンのシリアル出力を別GUIではなくqemuのコマンドをたたいたその場所に出力させることがある。この際、QEMUそのものの出力と仮想マシンがシリアル通信ポート (PL011)に書き込んだことによる出力が混在してしまって解析が行いにくい時がある。
-serial
オプションと-chardev
オプションを組み合わせることでシリアル通信用のコンソールとQEMUを立ち上げたコンソールを別々に用意することができる。最新版であるQEMU 8.2.0を使ってこの方法を紹介していく。
8.2.0におけるhelp表示の関係する部分を確認する。まずは-chardev
に関する箇所は以下のようになっている。
Character device options:
-chardev help
-chardev null,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev socket,id=id[,host=host],port=port[,to=to][,ipv4=on|off][,ipv6=on|off][,nodelay=on|off]
[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off]
[,logfile=PATH][,logappend=on|off][,tls-creds=ID][,tls-authz=ID] (tcp)
-chardev socket,id=id,path=path[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds]
[,mux=on|off][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off] (unix)
-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]
[,localport=localport][,ipv4=on|off][,ipv6=on|off][,mux=on|off]
[,logfile=PATH][,logappend=on|off]
-chardev msmouse,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]
[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev ringbuf,id=id[,size=size][,logfile=PATH][,logappend=on|off]
-chardev file,id=id,path=path[,input-path=input-file][,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev pipe,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev pty,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev stdio,id=id[,mux=on|off][,signal=on|off][,logfile=PATH][,logappend=on|off]
-chardev braille,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev serial,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev parallel,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]
chardevに関しては-chardev help
で次のような表示が行えるとかかているので実行すると下記が出力された。
qemu-system-x86_64 -chardev help
Available chardev backend types:
ringbuf
mux
pipe
stdio
pty
null
msmouse
socket
braille
vc
parallel
dbus
memory
udp
file
wctablet
serial
testdev
次に-serial
に関する場所をみると下記。
Debug/Expert options:
-compat [deprecated-input=accept|reject|crash][,deprecated-output=accept|hide]
Policy for handling deprecated management interfaces
-compat [unstable-input=accept|reject|crash][,unstable-output=accept|hide]
Policy for handling unstable management interfaces
-fw_cfg [name=]<name>,file=<file>
add named fw_cfg entry with contents from file
-fw_cfg [name=]<name>,string=<str>
add named fw_cfg entry with contents from string
-serial dev redirect the serial port to char device 'dev'
-parallel dev redirect the parallel port to char device 'dev'
-monitor dev redirect the monitor to char device 'dev'
-qmp dev like -monitor but opens in 'control' mode
-qmp-pretty dev like -qmp but uses pretty JSON formatting
-mon [chardev=]name[,mode=readline|control][,pretty[=on|off]]
-debugcon dev redirect the debug console to char device 'dev'
こちらは断片的な情報しかなくこれだけ見てオプションを考えることは難しい(QEMUは他もそうだが)
この使用例は-serial
のヘルプには書かれていないが下記のようにして使える。
qemu-system-x86_64 \
-chardev socket,id=uart,path=/tmp/qemu.socket,server=on \
-serial chardev:uart \
......
]]>
また、runqemuコマンド自体はYoctoのシステム自体でビルドされたqemuバイナリがない場合はホストシステムにインストールされているqemuを探して起動するようになっている。
def find_qemu(self):
qemu_bin = os.path.join(self.bindir_native, self.qemu_system)
# It is possible to have qemu-native in ASSUME_PROVIDED, and it won't
# find QEMU in sysroot, it needs to use host's qemu.
上記はrunqemuの当該部分から抜粋。
最初にlocal.confに対する記述のみでqemu-nativeおよびqemu-helper-nativeを外したい場合にとれる対策は下記を記載することである。
EXTRA_IMAGEDEPENDS:remove = "qemu-system-native"
EXTRA_IMAGEDEPENDS:remove = "qemu-helper-native:do_addto_recipe_sysroot"
これは下記のようにして導出されたもの。
1) bitbake -eで EXTRA_IMAGEDEPENDSに入っているqemu関連のターゲットを探す 2) それらをすべてlocal.confからremoveする
poky/meta/recipes-core/packagegroups/nativesdk-packagegroup-sdk-host.bbにあるnativesdk-qemuおよびnativesdk-qemu-helperを除去する。
RDEPENDS:nativesdk-packagegroup-sdk-host:remove = "nativesdk-qemu"
RDEPENDS:nativesdk-packagegroup-sdk-host:remove = "nativesdk-qemu-helper"
こちらは.bbに書かれているものなのでbbappendで上位レイヤから除去してもよい。RDEPENDSの打ち消しの際にはpn-は必要ないようだ。
meta/recipes-core/meta/meta-extsdk-toolchain.bbにあるqemu-nativeおよびqemu-helper-nativeを除去する。
DEPENDS:pn-meta-extsdk-toolchain:remove = "qemu-native"
DEPENDS:pn-meta-extsdk-toolchain:remove = "qemu-helper-native"
以上の箇所を環境に応じてチェックすることでbitbakeで目的のターゲットソフトを構築する際に不要なqemu-native系およびその依存ビルドの時間を削減することができるだろう。
QEMUはq35やvirtのような仮想のハードウェア以外に、実際に存在するハードウェア(ラズパイ等)のエミュレーションも行えるためBSP (Board Support Package)が非常によくできている(=完全にYoctoのコンセプトに従って完成されている)場合はBSPの対象ハードウェアをエミュレーションするためのQEMUをビルド環境として構築してくれるだろう。ただ現状は単にビルド時間の浪費となっているBSPが多いのではないかと思う。
]]>Hint: The Certificate Authority failed to verify the temporary Apache configuration changes made by Certbot. Ensure that the listed domains point to this Apache server and that it is accessible from the internet.
Some challenges have failed.
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.
まずはメッセージ通り/var/log/letsencrypt/letsencrypt.logを参照してエラーの内容を確認する。このファイルはsudo付きのcertbotコマンドによって作成されたと思われるため必要に応じて閲覧時にもsudoを使用するなどする。すると末尾で下記のようなメッセージが確認された
2024-01-14 19:16:27,451:INFO:certbot._internal.auth_handler:Challenge failed for domain mydomain.com
2024-01-14 19:16:27,451:INFO:certbot._internal.auth_handler:http-01 challenge for mydomain.com
そこでHTTP-01とは何かについて調べながら.logのより上部を参照する。すると次のような流れによってサーバの素性を確認するものだとわかった。
以上によってサーバの素性確認が完了すると残る認証プロセスに移る。ここで被認証サーバとはエラー例におけるmydomain.comのことを指す。Apacheの一時的な設定が行われている内容はletsencrypt.log上では次のようになっていた。
2024-01-14 19:16:23,026:DEBUG:certbot_apache._internal.http_01:Adding a temporary challenge validation Include for name: mydomain.com in: /etc/apache2/sites-enabled/000-default.conf
2024-01-14 19:16:23,026:DEBUG:certbot_apache._internal.http_01:writing a pre config file with text:
RewriteEngine on
RewriteRule ^/\.well-known/acme-challenge/([A-Za-z0-9-_=]+)$ /var/lib/letsencrypt/http_challenges/$1 [END]
2024-01-14 19:16:23,026:DEBUG:certbot_apache._internal.http_01:writing a post config file with text:
<Directory /var/lib/letsencrypt/http_challenges>
Require all granted
</Directory>
<Location /.well-known/acme-challenge>
Require all granted
</Location>
このアクセスのログがApache側に残っていればエラーの内容が確認できるだろう。Apacheのログは通常/var/log/apacheにある。Apacheのログに.well-known/acme-challenge関連のアクセスログがない場合はポート転送の設定が間違っていてLetsEncrypt認証サーバから被認証サーバに対するhttp経由の接続ができていないなどが考えられる。Apache側の設定はcertbotがうまいことやるだろうからこのケースが大半。
このログは下記のようにLetsEncrypt認証サーバのレスポンスメッセージとして受信したものをそのまま表示したものと思われる。
"type": "http-01",
"status": "invalid",
"error": {
"type": "urn:ietf:params:acme:error:dns",
"detail": "no valid A records found for mydomain.com; no valid AAAA records found for mydomain.com",
"status": 400
},
この場合はmydomain.comを
など、DNSレコードの状態をWAN側からチェックできるウェブサイトにmydomain.comを打ち込んでみるのが良いだろう。後者のunboundtestの場合はANSWER SECTIONにWAN側のIPアドレスが表示されていれば正常。
]]>:
or _
to efficiently describe what we want to do. This significantly reduce the amount of bb/bbappend code because we do not have to write explicit branching scripts at all in many cases. However, the problem is that key operator character had been changed from _
to :
since a version of Yocto distribution. The conversion is available for forward distribution upgrade. But backward one is still not available in official distribution as far as I observed.
The conversion method is too simple to wait or search formal conversion tools. I wrote simple script below to skip boring manual backward conversion tasks, when I was working on porting tasks from newer recipes syntax to old one.
#!/usr/bin/env bash
[[ -f $1 ]] || exit
sed -i "s=^\([A-Z]*\)\:=\1_=g" "$1"
sed -i "s=\:\(append\)=_\1=g" "$1"
sed -i "s=\:\(prepend\)=_\1=g" "$1"
This script can be used with wrapping one liner like
find meta* -name "*.bb*" | xargs -n1 dunfellize.sh
dunfellize.sh contains above script. There are many room to update and improve but it just works now !!!
]]>Linux kernel upstream repository contains "bootchart" scripts written in Perl to visualize initcall_debug
output. The Perl script parses dmesg output text and generate SVG format text to standard output. The saved SVG text can be opened by Web browser and any other svg compatible viewer.
However the visual of that SVG file is not so good.
T.B.D.
def bootchart_initcall(ax, data, label):
tab10 = pyplot.get_cmap('tab10')
ax.broken_barh(
data,
(-0.5, 0.5),
facecolors=[tab10(i % 10) for i in range(len(data)-1)]
)
ax.set_ylim([-1.1, 0.1])
ax.set_xlim([0.2, 1.3])
fontsize = 12
while fontsize > 0.1:
textbase = -10000
bbox = None
artists = []
for i in range(len(data)-1):
if data[i][1] < 0.0002:
continue
dataaxis = data[i][0] + data[i][1]/2
widthaxis = -0.5
textaxis = dataaxis
if dataaxis < textbase:
textaxis = textbase
text = ax.text(textaxis, widthaxis - 0.25,
label[i], rotation=270, rotation_mode='anchor', fontsize=fontsize)
if bbox is None:
bbox = _get_text_bbox(ax, text)
textbase = textaxis + bbox.width
text.set_x(textaxis - bbox.width/2)
artists.append(text)
if textbase < data[-1][0]*1.5:
datac = (data[0][0] + data[-1][0] + data[-1][1])/2
textc = (data[0][0] + textbase)/2
d = textc - datac
for text in artists:
x, _ = text.get_position()
text.set_x(x - d)
break
fontsize *= 0.95
for text in artists:
text.remove()
artists.clear()
j = 0
for i...
]]>
matplotlibはウィンドウだけではなくラスタ画像やベクタ形式のsvgやpdfに図を書き出すことも出来る。ベクタ形式の図はLaTeXに組み込んで論文やbeamerに載せるのに適している。適切なTeXディストリビューションをインストールしておけば図の中に数式を載せることも簡単に出来る。デフォルトの装飾だとmatplotlibによる図はすぐにそれだとわかるが、ひとたびデフォルトの装飾をやめればMATLABやgnuplotで作ったといってもわからないものとなる。もっとも、MATLABに関してはmatplotlib自体にMATLABのスタイルを模するオプションがあったと記憶しているが。
LaTeX/beamerにmatplotlib製のpdfを組み込むということをしていると、データに基づくグラフに限らない図形やアノテーションもmatplotlibで作ってしまえということがよく起こる。LaTeX自体にもTikzといった描画機能はあるものの、日ごろからmatplotlibを使い込んでいるとTikzなどをイチから覚えるよりもmatplotlibのアノテーションやパッチやアーティストを調べた方が全く同じクオリティのものがより素早く作れると考えるからだ。
であると、次に考えることはドキュメント自体をmatplotlibで作ってしまえないのか?ということであるが、これも当然出来るようだ。
オブジェクトマナーによるmatplotlibの使い方を念頭におく。オブジェクトマナーといっているのはpyplot
からplot
を呼び出してカレントのfigureに対してプロットを行うといった使い方ではなく、プロットはfigure
オブジェクトに追加されているaxes
オブジェクトに対して行うマナーのことだ。オブジェクト指向という言葉はいろいろ衝突するので使うことをやめた。
1ページを表現するのに1つのfigure
オブジェクトを用いる。このfigure
オブジェクトがpdfの1ページになるので、pdfドキュメントというからには適切なサイズ設定を行っておく。figure
オブジェクトのサイズはpyplot.figure()
に対してfigsize
キーワードで幅、高さのタプルを指定することで設定可能だが、これを以下のようにやる。
from matplotlib import pyplot
paperwidth_mm = 297
paperheight_mm = 210
mm_per_inch = 25.4
figsize = (paperwidth_mm/mm_per_inch, paperheight_mm/mm_per_inch)
fig = pyplot.figure(figsize=figsize)
ここではA4のドキュメントを例にした。figsize
に渡すべき幅と高さはインチ単位なので単にミリメートルと変換して渡してやればよい。beamerの場合はミリメートルではなく4:3や16:9などの比率を考慮することと、ピクセル数で指定したい場合は別途DPI(Depth per Inch)の決定が必要となる。DPIは印刷やディスプレイへの表示の文脈でよく出くわす出力系統の解像度を示しており用途に合わせて妥当な数字をもってきて計算する必要があるがここでは深入りすることはやめる。
結果は下記。
import matplotlib
matplotlib.use('pdf') # ウィンドウを表示させない
from matplotlib import pyplot
figures = []
# ページごとにfigureオブジェクトを作成し、中身を描画してfigures.append
from matplotlib.backends import backend_pdf
with backend_pdf.PdfPages('figure.pdf') as pdf:
for fig in pdf_figures:
pdf.savefig(fig)
pyplot.close('all')
Multipage PDFを参考にすればストレートに書ける内容となる。matplotlib.use('pdf')
が無くとも動くが、これがあるとpdfでの出力しかしないのに実行時にウィンドウのフォーカスが変わる挙動やx11 forwardingが起きる挙動となるため抑制しておく。
以上の内容で日ごろからfigure
にアノテーションやaxes
を置いたりしていれば同じようにドキュメンテーションを丁寧に読んでやるだけでなんちゃってLaTeXのような感じで図入りドキュメントが作れる。複数行の数式入りテキストを好きな場所に置くことも出来るので、段組みとか脚注とかタイプセットのコア機能を使わないような図8-9割のページが続くようなドキュメントだったらどうとでもなるのではないだろうか。別に複数ページである必要はないのだが、subplots
の次元が2を超えてくると(わかるかな、この表現)複数ページが超ありがたいと感じるようになると考えている。
良く使うフレーズとして、狙った位置にaxes
を置くコードを置いておく。
# figsize: 前述のもの
# padding_mm: ミリメートル単位のパディング
padding = padding_mm / mm_per_inch
rect = (
padding / figsize[0],
padding / figsize[1],
(figsize[0] - padding*2) / figsize[0],
(figsize[1] - padding*2) / figsize[1]
)
fig.add_axes(rect=rect)
add_axes
に渡すrect
キーワード引数の4つのタプルの値の意味がパーセンテージであることと後半2つの引数の意味が座標ではなくて幅と高さだということを言っている。パディングは例だが適宜テキストを入れ込みたい側を広げるなりするのがよくあるやり方だろう。
座標を直接指定するオブジェクトの配置場所をすぐに把握できるようにfigure
全体に補助線を入れるとか考えられる。ただ、いろいろ凝りすぎには注意。補助線はまだグレーだが複数行テキストを差し込み始めたらbeamerとかに戻り始めた方がよさそうである。
repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r18
repo sync
r18だと不要。
[100% 23337/23337] Target super fs image for debug: out/target/product/trout_x86/super.img
2022-10-16 03:07:47 - build_super_image.py - INFO : Building super image from info dict...
2022-10-16 03:07:47 - common.py - INFO : Running: "/mnt/ext4hdd/android-platform/out/host/linux-x86/bin/lpmake --metadata-size 65536 --super-name super --metadata-slots 3 --virtual-ab --device super:7516192768 --group google_system_dynamic_partitions_a:5771362304 --group google_system_dynamic_partitions_b:5771362304 --partition product_a:readonly:195928064:google_system_dynamic_partitions_a --image product_a=out/target/product/trout_x86/product.img --partition product_b:readonly:0:google_system_dynamic_partitions_b --partition system_a:readonly:965472256:google_system_dynamic_partitions_a --image system_a=out/target/product/trout_x86/system.img --partition system_b:readonly:27615232:google_system_dynamic_partitions_b --image system_b=out/target/product/trout_x86/system_other.img --partition system_ext_a:readonly:348798976:google_system_dynamic_partitions_a --image system_ext_a=out/target/product/trout_x86/system_ext.img --partition system_ext_b:readonly:0:google_system_dynamic_partitions_b --partition system_dlkm_a:readonly:348160:google_system_dynamic_partitions_a --image system_dlkm_a=out/target/product/trout_x86/system_dlkm.img --partition system_dlkm_b:readonly:0:google_system_dynamic_partitions_b --group google_vendor_dynamic_partitions_a:1472200704 --group google_vendor_dynamic_partitions_b:1472200704 --partition odm_a:readonly:860160:google_vendor_dynamic_partitions_a --image odm_a=out/target/product/trout_x86/odm.img --partition odm_b:readonly:0:google_vendor_dynamic_partitions_b --partition vendor_a:readonly:124334080:google_vendor_dynamic_partitions_a --image vendor_a=out/target/product/trout_x86/vendor.img --partition vendor_b:readonly:0:google_vendor_dynamic_partitions_b --partition vendor_dlkm_a:readonly:348160:google_vendor_dynamic_partitions_a --image vendor_dlkm_a=out/target/product/trout_x86/vendor_dlkm.img --partition vendor_dlkm_b:readonly:0:google_vendor_dynamic_partitions_b --partition odm_dlkm_a:readonly:348160:google_vendor_dynamic_partitions_a --image odm_dlkm_a=out/target/product/trout_x86/odm_dlkm.img --partition odm_dlkm_b:readonly:0:google_vendor_dynamic_partitions_b --output out/target/product/trout_x86/super.img"
2022-10-16 03:07:48 - build_super_image.py - INFO : Done writing image out/target/product/trout_x86/super.img
emulator bootconfig
emulator_car_x86_64:/proc # cat bootconfig
androidboot.qemu = "1"
androidboot.qemu.cpuvulkan.version = "4202496"
androidboot.qemu.settings.system.screen_off_timeout = "2147483647"
androidboot.qemu.vsync = "60"
androidboot.qemu.gltransport.name = "pipe"
androidboot.qemu.gltransport.drawFlushInterval = "800"
androidboot.qemu.adb.pubkey = ""
androidboot.qemu.camera_protocol_ver = "1"
androidboot.qemu.camera_hq_edge_processing = "0"
androidboot.qemu.virtiowifi = "1"
androidboot.qemu.hwcodec.avcdec = "2"
androidboot.qemu.hwcodec.hevcdec = "2"
androidboot.qemu.hwcodec.vpxdec = "2"
androidboot.qemu.avd_name = "<build>"
androidboot.hardware = "ranchu"
androidboot.serialno = "EMULATOR31X3X9X0"
androidboot.veritymode = "enforcing"
androidboot.opengles.version = "196608"
androidboot.debug.hwui.renderer = "skiagl"
androidboot.logcat = "*:V"
androidboot.dalvik.vm.heapsize = "512m"
androidboot.vbmeta.size = "6208"
androidboot.vbmeta.hash_alg = "sha256"
androidboot.vbmeta.digest...
]]>
Jenkinsにbitbakeさせる際に、どうしてもoe-init-build-envで失敗してしまっていた。なぜやら通るようになったのでその部分をメモする。
結果はこのようになる。パイプラインの書き方や出来ることはよくわからないがbitbakeが好きな場所で動かせるくらいはさすがに出来るようだ。
pipeline {
agent any
stages {
stage('clone') {
steps {
sh """
cd /path/to/hdd
git clone git://git.yoctoproject.org/poky -b dunfell poky_dunfell
"""
}
}
stage('bitbake') {
steps {
sh """
cd /path/to/hdd
. ./oe-init-build-env
bitbake core-image-minimal
"""
}
}
}
}
どうやらシェルがbashではないためsource
は使えないらしい。また、ドットスペースドットスラは必須のようだ(未検証)。
その他の参考ページ
sudo adduser git
su git
cd
mkdir .ssh && chmod 700 .ssh
touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys
これでローカルにgitというユーザが作成された。ssh://git@domain-name.com
という形式でのアクセスが可能になる。
ssh-keygen -t ed25519
で鍵ペアを生成し、すべてデフォルトの場合は~/.ssh/id_ed25519.pubの内容に次の内容を冒頭に付け足したものをgitユーザのauthorized_keysにアクセスさせる鍵の分だけ記入していく。
no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ed25519 <KEY> <MACHINE>
クライアント側には通常と同様に次のような~/.ssh/config
を用意しておく。
Host domain-name.com
User git
IdentityFile ~/.ssh/id_ed25519
次にセキュリティの観点でgitユーザのログインシェルをgit-shellに置換する。これを実行するとsu gitなどが出来なくなる。
which git-shell
/usr/bin/git-shell #控える
sudo vim /etc/shells #控えた箇所を追記
sudo chsh -s git $(which git-shell)
以上でOK。完全に本家のまま。
httpsとssh両方/srv/gitにフォルダを作ってアクセスさせる。
cd /srv
sudo mkdir git
sudo chmod g+w git
sudo chown git:www-data git
グループ書き込み権限とwww-dataグループを割り当てておく。所有者は前述したgitユーザにしておく。
Apache2をインストールする。
sudo apt update
sudo apt install apache2 apache2-utils
sudo a2enmod env cgi alias rewrite
次に、/etc/apache2/sites-enabled/000-default.conf
のVirtualHost要素内に次を追記する。
<VirtualHost *:80>
# git server configuration
SetEnv GIT_PROJECT_ROOT /srv/git
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git /usr/lib/git-core/git-http-backend/
<Directory "/usr/lib/git-core">
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
ここで
ScriptAlias /git /usr/lib/git-core/git-http-backend/
の真ん中/gitがアクセスするときのURLになる。このURLにアクセスしたとき、内容はGIT_PROJECT_ROOT
で指定した場所が探索される。最後はこのGIT_PROJECT_ROOT
すなわち/srv/git
の配下にベアリポジトリを作成するのみとなる。
ファイルの権限設定が面倒であるため参考ページと同様にスクリプトを用いる。
#!/usr/bin/env bash
GIT_PROJECT_ROOT=/srv/git
[[ -z $1 ]] && exit
REPOSITORY=$1
REPOSITORY=${REPOSITORY%\.git}.git
D="$GIT_PROJECT_ROOT/$REPOSITORY"
mkdir -p "$D"
GIT_DIR="$D" git init --bare
cp "$D/hooks/post-update.sample" "$D/hooks/post-update"
GIT_DIR="$D" git config http.receivepack true
GIT_DIR="$D" git config https.receivepack true
GIT_DIR="$D" git update-server-info
chown -R git:www-data "$D"
chmod -R...
]]>