非IT企業に勤める中年サラリーマンのIT日記

非IT企業でしかもITとは全く関係ない部署にいる中年エンジニア。唯一の趣味がプログラミングという”自称”プログラマー。

Ubuntu20.10でログアウトは地雷なのか?!なのでシャットダウンアプリをGo言語/Gtkで作った(というしょーもない話)

      2021/01/16

Ubuntu20.04から20.10に切り替わってすごく困ったのが「ログインループ」に陥ったことです。20.04のときは発生しなかったのになぜか20.10で出るようになりました。

ログインループとはログアウトした後に、再度ログインしようとしても受け付けてくれずログイン画面に戻ってしまう現象です。Ubuntuでは以前からよくある現象のようですね。解消方法はありますがライブCD(USB)を使わざるを得ないのでかなり面倒です。必ず出るわけではありませんが、たまにログイン時間が長くて肝を冷やします。

で、面白いのが僕のPCのみかもしれませんが、このログインループに陥るのはログアウト操作をした時のみなんです。自動サスペンドの場合は起きないんですよね。

そのログアウト操作なんですが、電源オフの下という微妙な位置にあって電源オフのつもりがうっかりログアウトをクリックしちゃうんです。UX的に設計ミスなんじゃないでしょうか。まさに地雷です。

 

 

で、どうしたかと言うとシャットダウンアプリ作った

めったにログアウト操作しない僕としては、電源オフか再起動できれば良いわけです。コマンドで「shutodown -h now」って打つのも面倒なので、クリックでシャットダウンと再起動ができるアプリを作ってしまいました。↓こんなやつ。

 

これを画面右上に設置して完成。プルダウンメニューを開かずにこのアイコンをダブルクリックすればアプリを介してシャットダウンできます。これで事故が起こらないと。

 

ソースコード

Go言語で作りました。GUIはGtkを使用。Go言語を選んだ理由はダブルクリック実行ができるからなんですよね。gccもRustもコマンドラインで./実行ファイルってやらないとダメなんですが、なぜかGoだけはダブルクリック実行ができるので。

UIはGladeで作りました。Go言語でGladeを使ってGTK+3プログラミングについては以下の記事を参照ください。

 

で、ソースコードを置いておきます。

package main

import (
  "github.com/gotk3/gotk3/gtk"
  "fmt"
  "os/exec"
  "os"
  "path/filepath"
)

func main() {
  exe, _ := os.Executable()
  fmt.Println(exe)
  fname := filepath.Dir(exe) + "/frame.glade"
  fmt.Println(fname)

  gtk.Init(nil)go
  builder, _ := gtk.BuilderNew()
  builder.AddFromFile(fname)
  obj, _ := builder.GetObject("window1")
  window := obj.(*gtk.Window)
  window.Connect("destroy", gtk.MainQuit)

  obj01, _ := builder.GetObject("shutdownBtn")
  btn1 := obj01.(*gtk.Button)
  obj02, _ := builder.GetObject("rebootBtn")
  btn2 := obj02.(*gtk.Button)

  btn1.Connect("clicked", func() {
    err := exec.Command("shutdown", "-h", "now").Run()
    fmt.Println(err)
  })

  btn2.Connect("clicked", func() {
    err := exec.Command("shutdown", "-r", "now").Run()
    fmt.Println(err)
  })

  window.ShowAll()
  gtk.Main()
}
 

 

 

gladeのソースはこちら。

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="window1">
    <property name="can_focus">False</property>
    <property name="window_position">center</property>
    <property name="default_width">300</property>
    <property name="default_height">100</property>
    <child type="titlebar">
      <placeholder/>
    </child>
    <child>
      <object class="GtkBox">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <property name="spacing">6</property>
        <property name="homogeneous">True</property>
        <child>
          <object class="GtkButton" id="shutdownBtn">
            <property name="label" translatable="yes">Shut down</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkButton" id="rebootBtn">
            <property name="label" translatable="yes">Reboot</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>
 

 

スポンサーリンク

 - Go言語, Gtk, 技術系コラム