conky の設定を晒す

前ふり

Ubuntu 18.10 にアップグレードした時に困ったこととして、アナログ時計アプリ cairo clock のパッケージが無くなってしまったこと。デジタル時計アプリは幾つかパッケージが有るけれど、アナログ時計は意外と少ない。もちろん古くから有る xclock は残っているが、これはウィンドウ枠やタイトルが消さない。

そんなわけで定番システム・モニター conky でアナログ時計を表示させることとしたのを機に、conky の設定を晒す。

設定を晒すだけなので、設定内容の意味はググって。

私のデスク・トップ

幾つかの Gnome Extension を入れて標準状態と異なっているが、conky の描画部分はデスク・トップ右上部。

デスク・トップ画像

表示しているのは

  • 今日、明日、明後日の天気予報 (現在地に出来れば良いが、やり方が不明なので URL 直打ち)
  • 直近 3 つの地震
  • アナログ時計
  • 先月、今月、来月のカレンダー
  • CPU の温度と使用量
  • メモリー使用量
  • CPU 負荷トップ 5 のプロセス
  • ディスク使用量とディスク・アクセス
  • ネットワーク状況 (Wi-Fi 時はアクセスポイント)

準備

(2022/09/06 更新)

Ubuntu 標準の conky だと、テキスト情報をしか載せられないので、アナログ時計が表示できないので、次のパッケージをインストール。ウェブデータの取得には Python 使う。

sudo apt install -y conky-all python3-bs4

~/.config/conky/conky.conf

conky の設定ファイルは以前 ~/.conkyrc だったが最近はこちら。

conky.config で始まる部分が全体の設定で、conky.text で始まる部分が表示する項目。

少し変わった設定をしているのは

conky.config = { alignment = 'top_left', background = true, border_width = 1, cpu_avg_samples = 4, default_color = 'black', default_outline_color = 'white', default_shade_color = 'white', draw_borders = false, draw_graph_borders = true, draw_outline = false, draw_shades = false, use_xft = true, gap_x = 1565, gap_y = 40, maximum_width = 350, minimum_width = 5, minimum_height = 5, net_avg_samples = 4, no_buffers = true, out_to_console = false, out_to_stderr = false, extra_newline = false, own_window = true, own_window_class = 'Conky', own_window_type = 'desktop', stippled_borders = 0, update_interval = 1.0, uppercase = false, use_spacer = 'none', show_graph_scale = false, show_graph_range = false, double_buffer = true, override_utf8_locale = true, font = 'Ricty Diminished:style=Regular:size=12', own_window_hints = 'undecorated,below,sticky,skip_taskbar,skip_pager', own_window_transparent = true, own_window_argb_visual = true, text_buffer_size = 512, lua_load = '~/bin/conky/clock.lua', lua_draw_hook_post = 'cairo_clock', }; conky.text = [[ ${execi 600 ~/bin/conky/weather.py } $hr ${execi 600 ~/bin/conky/earthquake.sh } $hr ${execi 600 ~/bin/conky/ncal3.sh } $hr CPU: ${execi 1 cat /sys/class/thermal/thermal_zone0/temp | awk '{printf("%.1f°C", ($1=$1 / 1000))}'} ${cpu cpu0}% ${color 880000}${cpubar cpu0}${color black} ${cpugraph cpu0 40,0 000088 000088} RAM: $mem/$memmax $memperc% ${color 880000}${membar}${color black} Swap: $swap/$swapmax $swapperc% ${color 880000}${swapbar}${color black} Name PID CPU% MEM% ${top name 1} ${top pid 1} ${top cpu 1} ${top mem 1} ${top name 2} ${top pid 2} ${top cpu 2} ${top mem 2} ${top name 3} ${top pid 3} ${top cpu 3} ${top mem 3} ${top name 4} ${top pid 4} ${top cpu 4} ${top mem 4} ${top name 5} ${top pid 5} ${top cpu 5} ${top mem 5} Disk: ${fs_used}/${fs_size} $fs_used_perc% ${color 880000}${fs_bar}${color black} ${diskiograph 40,0 000088 000088}# ${if_existing /proc/net/route enp0s31f6} networking: enp0s31f6 Up: ${upspeed enp0s31f6}${goto 200}Down: ${downspeed enp0s31f6} ${upspeedgraph enp0s31f6 30,160 000088 000088} ${downspeedgraph enp0s31f6 30,160 000088 000088} ${else if_existing /proc/net/route wlp2s0} networking: ${wireless_essid wlp2s0} Up: ${upspeed wlp2s0}${goto 200}Down: ${downspeed wlp2s0} ${upspeedgraph wlp2s0 30,160 000088 000088} ${downspeedgraph wlp2s0 30,160 000088 000088} ${endif} ]];

ネットワーク・デバイスを表す enp0s31f6, wlp2s0 は使用機器によって違うので、次のコマンドなどで調べる必要が有る

ip link

~/bin/conky/clock.lua

実際にアナログ時計を描画している Lua スクリプト

初めて書いた Lua スクリプトなので、きっともっとスマートに書き直せると思う (2024/11/07 更新)

#! /usr/bin/env lua -- conky + lua + cairo の時計 -- https://inajob.hatenablog.jp/entry/20110306/1299386373 を参考にした require 'cairo' require 'cairo_xlib' function conky_string_func() return os.date('%m/%d %H:%M') end cs, cr = nil function conky_cairo_clock() if conky_window == nil then return end if cs == nil or cairo_xlib_surface_get_width(cs) ~= conky_window.width or cairo_xlib_surface_get_height(cs) ~= conky_window.height then if cs then cairo_surface_destroy(cs) end cs = cairo_xlib_surface_create(conky_window.display, conky_window.drawable, conky_window.visual, conky_window.width, conky_window.height) end if cr then cairo_destroy(cr) end cr = cairo_create(cs) local r = math.min(conky_window.width, conky_window.height) * 0.39 -- 全体の大きさ conky を表示する縦横幅の最低値を基準とし ×0.39 倍で使用 local origine_x = conky_window.width - r/2 -2 -- 時計の中心 x 座標 (右端から半径分+αとして2) local origine_y = r/2 + 1 -- 時計の中心 y 座標 (左端からの半径分+αとして1 (ピッタリくっついていると見苦しく感じる)) -- 文字盤 cairo_set_source_rgba(cr, 0.93, 0.93, 0.93, 1) -- 文字盤の色指定 cairo_set_line_width(cr, 1) cairo_arc(cr, origine_x, origine_y, r/2, 0, 2 * math.pi) -- 円描画 cairo_fill_preserve(cr) -- 文字盤塗りつぶし cairo_set_source_rgba(cr, 0, 0, 0, 1) -- 文字盤の枠の色指定 cairo_stroke(cr) local ts = os.date('*t') local i,tr cairo_set_source_rgba(cr, 0, 0, 0, 1) -- 目盛りの色指定 -- 時間、5分毎の目盛り cairo_set_line_width(cr, 2.0) -- 1時間 (5分) 毎の目盛りの太さ for i = 0,11 do tr = math.pi * 2 * i / 12 cairo_move_to(cr, origine_x + 0.46*r*math.cos(tr), origine_y + 0.46*r*math.sin(tr)) cairo_line_to(cr, origine_x + r/2*math.cos(tr), origine_y + r/2*math.sin(tr)) cairo_stroke(cr) end -- 1分毎の目盛り cairo_set_line_width(cr, 1.0) -- 1分毎の目盛りの太さ for i = 0,59 do tr = math.pi * 2 * i / 60 cairo_move_to(cr, origine_x + 0.475*r*math.cos(tr), origine_y + 0.475*r*math.sin(tr)) cairo_line_to(cr, origine_x + r/2*math.cos(tr), origine_y + r/2*math.sin(tr)) cairo_stroke(cr) end -- 運針 -- hour tr = math.pi*2*(ts['hour']*60 + ts['min'])/(60*12) - math.pi/2 cairo_move_to(cr, origine_x - 0.08*r*math.cos(tr), origine_y - 0.08*r*math.sin(tr)) cairo_line_to(cr, origine_x + 0.04*r*math.cos(tr - math.pi/2), origine_y + 0.04*r*math.sin(tr - math.pi/2)) cairo_line_to(cr, origine_x + 0.35*r*math.cos(tr), origine_y + 0.35*r*math.sin(tr)) cairo_line_to(cr, origine_x + 0.03*r*math.cos(tr + math.pi/2), origine_y + 0.03*r*math.sin(tr + math.pi/2)) cairo_close_path(cr) cairo_set_source_rgba(cr, 0.5, 0.5, 0.5, 1) -- 針内部の色 cairo_fill_preserve(cr) cairo_set_source_rgba(cr, 0, 0, 0, 1) -- 針の輪郭色 cairo_stroke(cr) -- min tr = math.pi*2*(ts['min']*60 + ts['sec'])/(60*60) - math.pi/2 cairo_move_to(cr, origine_x - 0.08*r*math.cos(tr), origine_y - 0.08*r*math.sin(tr)) cairo_line_to(cr, origine_x + 0.04*r*math.cos(tr - math.pi/2), origine_y + 0.04*r*math.sin(tr - math.pi/2)) cairo_line_to(cr, origine_x + 0.44*r*math.cos(tr), origine_y + 0.44*r*math.sin(tr)) cairo_line_to(cr, origine_x + 0.04*r*math.cos(tr + math.pi/2), origine_y + 0.04*r*math.sin(tr + math.pi/2)) cairo_close_path(cr) cairo_set_source_rgba(cr, 0.5, 0.5, 0.5, 1) cairo_fill_preserve(cr) cairo_set_source_rgba(cr, 0, 0, 0, 1) cairo_stroke(cr) -- sec cairo_set_source_rgba(cr, 1, 0, 0, 1) -- 秒針の色指定 cairo_move_to(cr, origine_x - 0.15*r*math.cos(math.pi*2*ts['sec']/60 - math.pi/2), origine_y - 0.15*r*math.sin(math.pi*2*ts['sec']/60 - math.pi/2)) cairo_line_to(cr, origine_x + 0.425*r*math.cos(math.pi*2*ts['sec']/60 - math.pi/2), origine_y + 0.425*r*math.sin(math.pi*2*ts['sec']/60 - math.pi/2)) cairo_stroke(cr) cairo_set_source_rgba(cr, 1, 0, 0, 1) -- 中心円の色指定 cairo_set_line_width(cr, 1) cairo_arc(cr, origine_x, origine_y, 0.018*r, 0, 2 * math.pi) cairo_fill(cr) cairo_destroy(cr) cr = nil end

~/bin/conky/weather.py

(2022/09/06 更新)

天気予報を取得するスクリプト

https://tenki.jp/forecast/3/16/4410/13204/10days.html の部分は一度 日本気象協会 tenki.jp/ へ実際にアクセスして自分の居住地に合わせる必要がある

#!/usr/bin/env python3 # -*- coding: utf-8 -*- # vim:fileencoding=utf-8 fileformat=unix import requests import re from bs4 import BeautifulSoup html = requests.get('https://tenki.jp/forecast/3/16/4410/13204/10days.html') soup = BeautifulSoup(html.content, "html.parser") # print(soup) # 全体 for s in soup.find_all('dd', class_='forecast10days-actab')[:3]: # 最初の3日分 print(re.sub(r'(?<=\d)月', '/', re.sub(r'(?<=\d)日', '', s.find_all('div', class_='days')[0].text)) + s.find_all('div', class_='forecast')[0].text + ' ' + s.find_all('div', class_='temp')[0].text.replace('℃', '/', 1).replace('℃', '°C ') + s.find_all('div', class_='prob-precip')[0].text)

~/bin/conky/earthquake.sh

(2022/09/06 更新)

地震情報を取得するスクリプト

#!/bin/sh case "$(uname)" in Darwin|*BSD) sed="sed -E";; *) sed="sed -r";; esac w3m -T text/html -M -s -dump -cols 100000 -o pseudo_inlines=false https://earthquake.tenki.jp/bousai/earthquake/ | grep -E "^ +[0-9]+年[0-9]+月[0-9]+日 [0-9]+時[0-9]+分頃 +[^ ]+ +M[0-9.]+ +[0-9][強弱]?" | head --lines=3 | $sed "s/^ +[0-9]+年[0-9]+月([0-9]+日) ([0-9]+)時([0-9]+)分頃 +([^ ]+) +(M[0-9.]+) +([0-9][強弱]?)/\\1\\2:\\3\\5震度\\6\\4/g" exit 0

~/bin/conky/ncal3.sh

  • 月を跨いでも前後の週の同じ曜日を解りやすくするために ncal コマンドと似た形式で出力したい
  • しかし ncal コマンドの出力はパイプ経由すると当日の強調表示情報が消える
  • 出力の横幅を少なくするために、月を跨る空白要素は詰めたい

といった理由でシェル・スクリプトを使っている

#!/bin/sh case "$(uname)" in Darwin|*BSD) sed="sed -E";; *) sed="sed -r";; esac transpose(){ # 行・列を入れ替える (出力はタブ区切り) grep -vE "^ +$" | # スペースのみの行は除外 $sed 's/ / @ /g' | # 空白要素をダミーに置き換え nawk '{ # 実際の入れ替えルーチン for (i=1; i<=NF; i++) { a[NR,i] = $i } } NF>p { p = NF } END { for(j=1; j<=p; j++) { str=a[1,j]; for(i=2; i<=NR; i++){ str=str"\t"a[i,j]; } print str } }' | $sed 's/@//g' # ダミー削除 } calendar=$( LC_ALL=ja_JP.utf8 cal -3 ) # 日本語ロケールで前後3ヶ月取得 if cat <<-_EOF_ | $calendar _EOF_ # 出力が「何月何年」で始まる形式と先頭行に年が表示され、次の行に月だけ表示の形式が有る grep -Eq "^\\s*[0-9]{4}$" ; then # 西暦だけの行が有るか? 有れば calendar データは 2 行目以降を使う calendar=$( cat <<-_EOF_ | $calendar _EOF_ tail --line=+2 ) fi # 1行目の 何月 何年取得 month=$( cat <<- _EOF_ | $calendar _EOF_ head --line=1 ) # 曜日のみ+一週間分のみ week=$( cat <<- _EOF_ | $calendar _EOF_ head --line=2 | tail --line=1 | cut -b1-27 ) # 実際のカレンダー・日付部分 calendar=$( cat <<- _EOF_ | $calendar _EOF_ $sed -e 's/ _\x8([0-9])_\x8([0-9]) /<\1\2>/g' \ -e 's/ _\x8 _\x8([0-9]) / <\1>/g' | tail --line=+3 ) # 先月カレンダー last_month=$( cat <<- _EOF_ | $calendar _EOF_ cut -c1-21 ) # 今月カレンダー this_month=$( cat <<- _EOF_ | $calendar _EOF_ cut -c22-43 | $sed 's/(<[0-9]+>)/ \1 /g' ) # 来月カレンダー next_month=$( cat <<- _EOF_ | $calendar _EOF_ cut -c44-65 ) cat << _EOF_ | $month _EOF_ cut -b2-20,30-40,50-64 | sed -E -e 's/([0-9]+) *([0-9]+月)/\1 \2/g' cat << _EOF_ | $week $last_month $this_month $next_month _EOF_ transpose | $sed -e 's/([日月火水木金土])\t\t/\1 /g' \ -e 's/([日月火水木金土])\t/\1 /g' \ -e 's/\t\t/\t/g' \ -e 's/\t$//g' \ -e 's/\t(<[0-9][0-9])/\1/g' \ -e 's/\t([<0-9][0-9])/ \1/g' \ -e 's/\t/ /g' \ -e 's/> />/g' \ exit 0