ตัวบ่งชี้การใช้ระบบไฟล์


10

ฉันไม่พบยูทิลิตีที่เหมาะสมเพียงแค่ระบุการใช้งานระบบไฟล์ (% พื้นที่ว่างสำหรับพาร์ติชัน) บนพาเนล

และฉันไม่ได้รอที่จะติดตั้งเครื่องมือการจัดการเดสก์ท็อปชนิดใด ๆ ที่ไม่ดี แต่เป็นตัวบ่งชี้ที่ง่าย

ฉันขอขอบคุณข้อเสนอแนะทั้งหมดของคุณ


ที่สามารถนำไปปฏิบัติได้ คุณต้องการให้มันเป็นอย่างไร เพียงแค่ชื่ออุปกรณ์พาร์ทิชันที่ชอบ/dev/sdb1และการใช้งานที่อยู่ติดกับมัน ในหน่วยเปอร์เซ็นต์หรือจริงกิกะไบต์?
Sergiy Kolodyazhnyy

ฉันต้องการชื่อแบบกำหนดเองและ% ฟรีสำหรับพาร์ติชันทั้งหมดของ HDD และเมื่อฉันปลั๊กอิน xternal HDD หรือที่เก็บข้อมูล usb
Dinesh Kalidassan

คุณช่วยอธิบายชื่อที่กำหนดเองได้อย่างไร? คุณต้องการตั้งชื่อไดรฟ์ด้วยหรือไม่
Sergiy Kolodyazhnyy

ฉันต้องการอ้างถึง / dev / sdb1 เป็น "Critical" หรือ "Entertainment" หรือ "Official" เป็นต้น
Dinesh Kalidassan

2
สวัสดี Dinesh หากคำตอบใด ๆ ให้สิ่งที่คุณกำลังมองหา (โดยทั่วไป) คุณสามารถยอมรับได้ ฉันสังเกตเห็นในโปรไฟล์ของคุณว่าคุณไม่ได้รับคำตอบก่อนหน้านี้คุณอาจไม่คุ้นเคยกับมัน หาก (อย่างใดอย่างหนึ่ง) คำตอบข้อใดข้อหนึ่งแก้ปัญหาของคุณได้คุณจะพิจารณายอมรับมันหรือไม่? (ทำเครื่องหมาย V ใหญ่ด้านล่างลูกศรขึ้น / ลงถัดจากคำตอบ)
Jacob Vlijm

คำตอบ:


19

แก้ไข:

1. คำตอบใหม่

ในขณะที่คำตอบที่ด้านล่างของคำตอบนี้สามารถใช้ได้ (ดู[2.]) มันจะนำไปสู่ ​​- ppaรุ่นที่มีตัวเลือกเพิ่มเติมที่จะตั้งค่าในหน้าต่างการตั้งค่า

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

ตัวเลือกรวมถึง:

  • ตั้งชื่อแทนทั้งหมดในหน้าต่างเดียว
  • การตั้งค่าสีของธีมสำหรับไอคอนพาเนล:

    ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่

  • การตั้งค่าเกณฑ์สำหรับคำเตือน
  • แสดงข้อมูลเกี่ยวกับไดรฟ์ข้อมูลที่เชื่อมต่อ / เชื่อมต่อใหม่ในการแจ้งเตือน:

    ป้อนคำอธิบายรูปภาพที่นี่

  • ทำงานเมื่อเริ่มต้น

นอกจากนี้ตัวบ่งชี้ยังมีชุดไอคอน (ความกว้าง) ที่เล็กกว่าสำหรับ distro อื่น (เช่น xfce) ซึ่งจะถูกนำไปใช้โดยอัตโนมัติขึ้นอยู่กับตัวจัดการหน้าต่าง

ป้อนคำอธิบายรูปภาพที่นี่

ติดตั้ง:

sudo add-apt-repository ppa:vlijm/spaceview
sudo apt-get update
sudo apt-get install spaceview



2. คำตอบเดิม

สคริปต์ด้านล่างเป็นตัวบ่งชี้ที่แสดงรายการอุปกรณ์ของคุณและแสดงการใช้งาน ข้อมูลจะถูกอัพเดท (ถ้าจำเป็น) หนึ่งครั้งต่อสิบวินาที

ป้อนคำอธิบายรูปภาพที่นี่

นอกจากนี้

  • ในขณะที่ตัวบ่งชี้กำลังทำงานคุณสามารถเลือกอุปกรณ์ที่จะแสดงในไอคอน อุปกรณ์จะถูกจดจำในครั้งต่อไปที่คุณเรียกใช้ตัวบ่งชี้:

    ป้อนคำอธิบายรูปภาพที่นี่

    ! [ใส่คำอธิบายภาพที่นี่

    ป้อนคำอธิบายรูปภาพที่นี่

  • สำหรับอุปกรณ์หนึ่งตัวหรือมากกว่า (หรือทั้งหมด) คุณสามารถตั้งชื่ออื่น ("ชื่อที่กำหนดเอง") เพื่อตั้งค่าไว้ที่ส่วนหัวของสคริปต์

    เป็นตัวอย่างนี้:

    alias = [
        ["sdc1", "stick"],
        ["sdb1", "External"],
        ["sda2", "root"],
        ["sda4", "ntfs1"],
        ["sda5", "ntfs2"],
        ["//192.168.0.104/media", "netwerk media"],
        ["//192.168.0.104/werkmap_documenten", "netwerk docs"],
        ]
    

    จะแสดง:

    ป้อนคำอธิบายรูปภาพที่นี่

  • คุณสามารถตั้งค่าthreshhold ; หากพื้นที่ว่างของอุปกรณ์ใดอุปกรณ์หนึ่งของคุณอยู่ด้านล่างคุณจะได้รับคำเตือน:

    ป้อนคำอธิบายรูปภาพที่นี่

  • อุปกรณ์ที่เสียบ / ถอดปลั๊กจะถูกเพิ่ม / ลบออกจาก menulist ภายใน 10 วินาที

สคริปต์

#!/usr/bin/env python3
import subprocess
import os
import time
import signal
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3, GObject
from threading import Thread

#--- set alias names below in the format [[device1, alias1], [device2, alias2]]
#--- just set alias = [] to have no custom naming
alias = []
#--- set the threshold to show a warning below 
#--- set to 0 to have no warning
threshold = 17
#---
currpath = os.path.dirname(os.path.realpath(__file__))
prefsfile = os.path.join(currpath, "showpreferred")

class ShowDevs():
    def __init__(self):
        self.default_dev = self.get_showfromfile()
        self.app = 'show_dev'
        iconpath = currpath+"/0.png"
        self.indicator = AppIndicator3.Indicator.new(
            self.app, iconpath,
            AppIndicator3.IndicatorCategory.OTHER)
        self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)       
        self.indicator.set_menu(self.create_menu())
        self.indicator.set_label("Starting up...", self.app)
        self.update = Thread(target=self.check_changes)
        self.update.setDaemon(True)
        self.update.start()

    def check_changes(self):
        state1 = None
        while True:
            self.state2 = self.read_devices()
            if self.state2 != state1:
                self.update_interface(self.state2)
            state1 = self.state2
            time.sleep(10)

    def update_interface(self, state):
        warning = False; self.newmenu = []
        for dev in state:
            mention = self.create_mention(dev)
            name = mention[0]; deci = mention[2]; n = mention[1]
            if n <= threshold:
                warning = True
            try:
                if self.default_dev in name:
                    newlabel = mention[3]
                    newicon = currpath+"/"+str(10-deci)+".png"
            except TypeError:
                pass
            self.newmenu.append(name+" "+str(n)+"% free")
        if warning:
            newlabel = "Check your disks!"
            newicon = currpath+"/10.png"
        try:
            self.update_indicator(newlabel, newicon)
        except UnboundLocalError:
            labeldata = self.create_mention(state[0])
            newlabel = labeldata[3]
            newicon = currpath+"/"+str(10-labeldata[2])+".png"
            self.update_indicator(newlabel, newicon)
        GObject.idle_add(self.set_new, 
            priority=GObject.PRIORITY_DEFAULT)  

    def update_indicator(self, newlabel, newicon):
        GObject.idle_add(self.indicator.set_label,
            newlabel, self.app,
            priority=GObject.PRIORITY_DEFAULT)   
        GObject.idle_add(self.indicator.set_icon,
            newicon,
            priority=GObject.PRIORITY_DEFAULT)

    def set_new(self):
        for i in self.initmenu.get_children():
            self.initmenu.remove(i)
        for item in self.newmenu:
            add = Gtk.MenuItem(item)
            add.connect('activate', self.change_show)
            self.initmenu.append(add) 
        menu_sep = Gtk.SeparatorMenuItem()
        self.initmenu.append(menu_sep)
        self.item_quit = Gtk.MenuItem('Quit')
        self.item_quit.connect('activate', self.stop)
        self.initmenu.append(self.item_quit)
        self.initmenu.show_all()

    def change_show(self, *args):
        index = self.initmenu.get_children().index(self.initmenu.get_active())
        self.default_dev = self.newmenu[index].split()[0]
        open(prefsfile, "wt").write(self.default_dev)
        self.update_interface(self.read_devices())

    def create_mention(self, dev):
        name = dev[1] if dev[1] else dev[0]
        n = dev[2]; deci = round(dev[2]/10)
        newlabel = name+" "+str(n)+"% free"
        return (name, n, deci, newlabel)        

    def create_menu(self):
        # create initial basic menu
        self.initmenu = Gtk.Menu()
        self.item_quit = Gtk.MenuItem('Quit')
        self.item_quit.connect('activate', self.stop)
        self.initmenu.append(self.item_quit)
        self.initmenu.show_all()
        return self.initmenu

    def read_devices(self):
        # read the devices, look up their alias and the free sapace
        devdata = []
        data = subprocess.check_output(["df", "-h"]).decode("utf-8").splitlines()
        relevant = [l for l in data if all([
                    any([l.startswith("/dev/"), l.startswith("//")]),
                    not "/loop" in l])
                    ]
        for dev in relevant:
            data = dev.split(); name = data[0]; pseudo = None       
            free = 100-int([s.strip("%") for s in data if "%" in s][0])
            for al in alias:
                if al[0] in name:
                    pseudo = al[1]
                    break
            devdata.append((name, pseudo, free)) 
        return devdata

    def get_showfromfile(self):
        # read the preferred default device from file
        try:
            defdev = open(prefsfile).read().strip()
        except FileNotFoundError:
            defdev = None
        return defdev

    def stop(self, source):
        Gtk.main_quit()

ShowDevs()
GObject.threads_init()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()

ไอคอนต่างๆ

ป้อนคำอธิบายรูปภาพที่นี่ 0.png

ป้อนคำอธิบายรูปภาพที่นี่ 1.png

ป้อนคำอธิบายรูปภาพที่นี่ 2.png

ป้อนคำอธิบายรูปภาพที่นี่ 3.png

ป้อนคำอธิบายรูปภาพที่นี่ 4.png

ป้อนคำอธิบายรูปภาพที่นี่ 5.png

ป้อนคำอธิบายรูปภาพที่นี่ 6.png

ป้อนคำอธิบายรูปภาพที่นี่ 7.png

ป้อนคำอธิบายรูปภาพที่นี่ 8.png

ป้อนคำอธิบายรูปภาพที่นี่ 9.png

ป้อนคำอธิบายรูปภาพที่นี่ 10.png

การตั้งค่า

การตั้งค่าทำได้ง่าย:

  • คัดลอกสคริปต์ลงในไฟล์เปล่าบันทึกเป็น showusage.py
  • บันทึกไอคอนด้านบนชื่อตรงกับในป้ายกำกับของพวกเขาลงในหนึ่งและไดเรกทอรีเดียวกันกับสคริปต์ (คลิกขวา> บันทึกเป็น)
  • ในส่วนหัวของสคริปต์ให้ตั้งค่า (เป็นไปได้) ชื่อทางเลือก ( aliasses) ตัวอย่างด้านล่าง:

    alias = [
        ["sda2", "root"],
        ["sdb1", "External"]
        ]
    

    หากคุณต้องการแสดงอุปกรณ์ที่ไม่เปลี่ยนแปลงให้ใช้:

    alias = []

    ... และหากคุณต้องการให้เปลี่ยนเกณฑ์เพื่อแสดงคำเตือน:

    #--- set the threshold to show a warning below (% free, in steps of 10%)
    #--- set to 0 to have no warning
    threshold = 10
    

    แค่นั้นแหละ

ใช้มัน

หากต้องการใช้ตัวบ่งชี้ให้รันคำสั่ง:

python3 /path/to/showusage.py

หากต้องการเพิ่มลงในแอปพลิเคชันเริ่มต้นให้ใช้คำสั่ง:

/bin/bash -c "sleep 10 && python3 /path/to/showusage.py"

เลือกแอปพลิเคชัน: Dash> แอปพลิเคชั่นเริ่มต้น> เพิ่มเพิ่มคำสั่งด้านบน


16

ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียนตัวบ่งชี้นี้และมันถูกเขียนขึ้นสำหรับคำถามเฉพาะนี้

อัปเดต 23,2018

ตัวบ่งชี้ในขณะนี้สนับสนุน รายชื่อเครือข่ายหุ้น ขอบคุณmihaigalos

อัปเดต 29 ตุลาคม 2559

ตัวบ่งชี้ที่ตอนนี้มีฟังก์ชั่นยกเลิกการต่อเชื่อมและชื่อแทนได้รับการทำที่ไม่ซ้ำกันโดยอ้างถึง UUID sda1ของพาร์ทิชันแทนชื่อของแต่ละอุปกรณ์ป้องกันเช่น ดูรายงานข้อผิดพลาดที่เกี่ยวข้อง

อัปเดต 8 ต.ค. 2559

ขณะนี้ตัวบ่งชี้อยู่ในเวอร์ชัน 2.0 ได้เพิ่มคุณสมบัติบางอย่างและมี PPA ของตัวเอง

ในการติดตั้งจาก PPA ให้ใช้ขั้นตอนต่อไปนี้ในเทอร์มินัล:

  1. sudo apt-add-repository ppa:udisks-indicator-team/ppa
  2. sudo bash -c 'apt-get update && apt-get install udisks-indicator'

ตามที่ระบุไว้ในบันทึกย่อประจำรุ่นฟีเจอร์ต่างๆรวมถึง:

  • ไอคอนสำหรับรายการเมนู: แต่ละพาร์ติชั่น / อุปกรณ์มีไอคอนที่เหมาะสมติดอยู่ หากอุปกรณ์นั้นเป็นดิสก์ USB จะใช้ไอคอนสื่อบันทึกแบบถอดได้หากเป็นภาพ iso - จะใช้ไอคอนออปติคัลดิสก์และเห็นชัดว่าฮาร์ดไดรฟ์ / SSD พาร์ทิชันมีไอคอนไดรฟ์
  • การใช้งานจะแสดงเป็นเปอร์เซ็นต์และค่าที่มนุษย์อ่านได้ (พลัง 1024)
  • การแสดงกราฟิกของการใช้งานผ่านบาร์การใช้งาน (ขอบคุณมากสำหรับ Mateo Salta สำหรับแนวคิด)
  • ไดอะล็อกการกำหนดค่าตามความชอบ: ผู้ใช้สามารถปิดบางฟิลด์ที่ไม่ต้องการดูในแต่ละรายการเมนู สิ่งนี้ช่วยให้การรักษาเมนูตัวบ่งชี้สะอาดหากมีพาร์ติชันที่แนบมาจำนวนมาก (ขอบคุณคำขอของ Zacharee)
  • การเว้นวรรคข้อความ: ด้วยแบบอักษรเริ่มต้นของ Ubuntu และแบบอักษร Monospace รายการข้อความมีระยะห่างอย่างดีเพื่อให้ดูสะอาดตาและเพิ่มความสามารถในการอ่านข้อมูล
  • ฟองอากาศแจ้งเตือนในกรณีที่พาร์ทิชันไม่สามารถติดตั้ง

ด้านล่างเป็นสกรีนช็อตที่มีธีมไอคอน Ubuntu เริ่มต้น: ป้อนคำอธิบายรูปภาพที่นี่

ชุดไอคอน Ubuntu Kylin

ป้อนคำอธิบายรูปภาพที่นี่

เมื่อปิดฟิลด์ตัวเลือกทั้งหมด

ป้อนคำอธิบายรูปภาพที่นี่

ตัวเลือกการออกแบบและความคิดเพิ่มเติม:

ในการสร้างตัวบ่งชี้นี้ฉันหวังว่าจะได้รับประโยชน์ที่เหมาะสำหรับผู้ใช้ขั้นสูงและไม่เป็นทางการ ฉันพยายามที่จะแก้ไขปัญหาบางอย่างที่ฉันสังเกตเห็นว่าผู้ใช้ใหม่อาจมีกับการจัดการเครื่องมือบรรทัดคำสั่ง นอกจากนี้ยูทิลิตี้มุ่งมั่นที่จะอเนกประสงค์

ไดอะล็อกการกำหนดค่าตามความชอบอนุญาตให้สร้างตัวบ่งชี้ที่ซับซ้อนและ / หรือง่ายที่สุดเท่าที่ผู้ใช้ต้องการ มันเป็นการตัดสินใจที่เฉพาะเจาะจงในการออกแบบเพื่อหลีกเลี่ยงการติดป้ายบนแผงด้านบนเพื่อไม่ให้ใช้พื้นที่บนแผงควบคุมมากเกินไปของผู้ใช้ นอกจากนี้ตัวบ่งชี้นี้มุ่งมั่นที่จะเป็นยูทิลิตี้อเนกประสงค์ที่ช่วยให้การติดตั้งพาร์ทิชันเช่นเดียวกับการเปิดไดเรกทอรีที่เกี่ยวข้อง สิ่งนี้สามารถใช้งานได้ไม่เพียงแค่เป็นยูทิลิตีการใช้งานดิสก์ แต่ยังเป็นยูทิลิตี้การนำทางเพื่อเปิดไดเรกทอรีได้อย่างรวดเร็ว

mountนอกจากนี้ยังสะดวกสำหรับผู้ใช้ที่จะรู้ว่าพรายน้ำที่พาร์ทิชันดิสก์จึงหลีกเลี่ยงความสับสนบ่อยครั้งกับการติดตั้งสาธารณูปโภคผ่านบรรทัดคำสั่งเช่น แทนที่จะใช้udisksctlเพื่อจุดประสงค์นั้น (รวมถึงการได้รับข้อมูลจากUDisks2ภูตด้วยเหตุนี้จึงมีการตั้งชื่อ) งานเดียวที่ไม่ได้ดำเนินการคือยกเลิกการต่อเชื่อมและเหตุผลที่ทำให้Open Disks Utilityรายการเมนูรวมอยู่ด้วย

ในขณะที่ฉันพยายามอย่างยิ่งที่จะทำให้มันคล้ายกับเมนู iStat โครงการแตกต่างจากเป้าหมายนี้ - ตัวบ่งชี้มีเอกลักษณ์ในการออกแบบและวัตถุประสงค์ ฉันหวังว่ามันจะมีประโยชน์สำหรับผู้ใช้จำนวนมากและทำให้ประสบการณ์ Ubuntu ของพวกเขาน่าพอใจยิ่งขึ้น


udisks-indicator (คำตอบดั้งเดิม)

ตัวบ่งชี้สำหรับ Ubuntu พร้อมเดสก์ท็อป Unity เพื่อแสดงการใช้งานดิสก์ ภาพตัวอย่าง

ภาพรวม

ตัวบ่งชี้สำหรับ Ubuntu พร้อม Unity นี้จะช่วยให้สามารถดูข้อมูลเกี่ยวกับพาร์ติชันที่ติดตั้งของคุณได้อย่างง่ายดาย มันพยายามที่จะคล้ายกับ iStat Menu 3 menulet จาก OS X

มีการจัดเรียงรายการตามลำดับ:

  • กั้น
  • นามแฝง (ถ้ากำหนดโดยผู้ใช้)
  • ดิสก์ไดรฟ์ที่เป็นเจ้าของพาร์ติชัน
  • Mountpoint ของพาร์ติชัน (ไดเรกทอรี)
  • % การใช้งาน

การคลิกที่รายการพาร์ติชั่นแต่ละรายการจะเปิดเมานต์พาร์ติชั่นในตัวจัดการไฟล์เริ่มต้น

เมนู "พาร์ติชัน Unmounted" แสดงรายการพาร์ติชันทั้งหมดที่ไม่ได้เมาท์ในขณะนี้โดยระบบ การคลิกที่รายการใด ๆ ในเมนูย่อยนั้นจะทำการเมานท์พาร์ติชั่นนั้นโดยอัตโนมัติไปยัง/media/username/drive-idโฟลเดอร์

ตัวบ่งชี้จะใช้ไอคอนเริ่มต้นที่มาพร้อมกับระบบดังนั้นไอคอนควรเปลี่ยนตามที่คุณเปลี่ยนธีมไอคอนโดยใช้ Unity Tweak Tool หรือวิธีอื่น

หมายเหตุ : หากคุณต้องการเพิ่มชื่อแทนหลายรายการพร้อมกันแทนที่จะเลือกทีละชื่อโดยใช้ตัวเลือก "สร้างชื่อแทน" คุณสามารถทำได้โดยแก้ไข~/.partition_aliases.jsonไฟล์กำหนดค่า รูปแบบดังต่อไปนี้:

{
    "sda1": "Alias 1",
    "sda2": "Alias 2",
    "sdb1": "Alias 3"
}

การติดตั้ง

PPA สำหรับการติดตั้งง่ายกำลังจะมาเร็ว ๆ นี้ . .

ในระหว่างนี้นี่เป็นขั้นตอนทางเลือก:

  1. cd /tmp
  2. wget https://github.com/SergKolo/udisks-indicator/archive/master.zip
  3. unzip master.zip
  4. sudo install udisks-indicator-master/udisks-indicator /usr/bin/udisks-indicator
  5. sudo install udisks-indicator-master/udisks-indicator.desktop /usr/share/applications/udisks-indicator.desktop

ขั้นตอนเหล่านี้ทั้งหมดสามารถใส่ลงในสคริปต์การติดตั้งเล็กน้อย:

#!/bin/bash

cd /tmp
rm master.zip*
wget https://github.com/SergKolo/udisks-indicator/archive/master.zip
unzip master.zip
install udisks-indicator-master/udisks-indicator /usr/bin/udisks-indicator
install udisks-indicator-master/udisks-indicator.desktop /usr/share/applications/udisks-indicator.desktop

รหัสแหล่งที่มา

ซอร์สโค้ดต้นฉบับ (เวอร์ชั่น v1.0) ที่มีฟังก์ชันการทำงานพื้นฐานของตัวบ่งชี้นี้อยู่ด้านล่าง สำหรับคุณสมบัติใหม่ล่าสุดให้ตรวจสอบที่เก็บ GitHub สำหรับโครงการนี้ โปรดรายงานคำขอคุณลักษณะใด ๆ รวมถึงข้อผิดพลาดใน GitHub

The /usr/bin/udisks-indicator:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

#
# Author: Serg Kolo , contact: 1047481448@qq.com
# Date: September 27 , 2016
# Purpose: appindicator for displaying mounted filesystem usage
# Tested on: Ubuntu 16.04 LTS
#
#
# Licensed under The MIT License (MIT).
# See included LICENSE file or the notice below.
#
# Copyright © 2016 Sergiy Kolodyazhnyy
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import gi
gi.require_version('AppIndicator3', '0.1')
from gi.repository import GLib as glib
from gi.repository import AppIndicator3 as appindicator
from gi.repository import Gtk as gtk
from os import statvfs
#from collections import OrderedDict
import subprocess
import shutil
import dbus
import json
import os

class UdisksIndicator(object):

    def __init__(self):
        self.app = appindicator.Indicator.new(
            'udisks-indicator', "drive-harddisk-symbolic.svg",
            appindicator.IndicatorCategory.HARDWARE
            )

        if not self.app.get_icon():
           self.app.set_icon("drive-harddisk-symbolic")

        self.app.set_status(appindicator.IndicatorStatus.ACTIVE)

        filename = '.partition_aliases.json'
        user_home = os.path.expanduser('~')
        self.config_file = os.path.join(user_home,filename)
        self.cache = self.get_partitions()
        self.make_menu()
        self.update()


    def update(self):
        timeout = 5
        glib.timeout_add_seconds(timeout,self.callback)

    def callback(self):
        if self.cache != self.get_partitions():
            self.make_menu()
        self.update()        

    def make_menu(self,*args):
        """ generates entries in the indicator"""
        if hasattr(self, 'app_menu'):
            for item in self.app_menu.get_children():
                self.app_menu.remove(item)

        self.app_menu = gtk.Menu()

        partitions = self.get_partitions()
        for i in partitions:

            part = "Partition: " + i[0]
            alias = self.find_alias(i[0])
            drive = "\nDrive: " + i[1]
            mount = "\nMountPoint: " + i[2]
            usage = "\n%Usage: " + i[3]

            item = part + drive + mount + usage
            if alias:
                alias = "\nAlias: " + alias
                item = part + alias + drive + mount + usage

            self.menu_item = gtk.MenuItem(item)
            self.menu_item.connect('activate',self.open_mountpoint,i[2])
            self.app_menu.append(self.menu_item)
            self.menu_item.show()

            self.separator = gtk.SeparatorMenuItem()
            self.app_menu.append(self.separator)
            self.separator.show()

        self.unmounted = gtk.MenuItem('Unmounted Partitions')
        self.unmounted_submenu = gtk.Menu()
        self.unmounted.set_submenu(self.unmounted_submenu)

        for i in self.get_unmounted_partitions():

            # TODO: add type checking, prevent swap

            part = "Partition: " + i[0]
            alias = self.find_alias(i[0])
            drive = "\nDrive: " + i[1]
            label = part + drive
            if alias: 
               alias = "\nAlias: " + alias
               label = part + alias + drive

            self.menu_item = gtk.MenuItem(label)
            self.menu_item.connect('activate',self.mount_partition,i[0])
            self.unmounted_submenu.append(self.menu_item)
            self.menu_item.show()

            self.separator = gtk.SeparatorMenuItem()
            self.unmounted_submenu.append(self.separator)
            self.separator.show()

        self.app_menu.append(self.unmounted)
        self.unmounted.show()


        self.separator = gtk.SeparatorMenuItem()
        self.app_menu.append(self.separator)
        self.separator.show()

        self.make_part_alias = gtk.MenuItem('Make Alias')
        self.make_part_alias.connect('activate',self.make_alias)
        self.app_menu.append(self.make_part_alias)
        self.make_part_alias.show()

        user_home = os.path.expanduser('~')
        desktop_file = '.config/autostart/udisks-indicator.desktop'
        full_path = os.path.join(user_home,desktop_file)

        label = 'Start Automatically' 
        if os.path.exists(full_path):
           label = label + ' \u2714'
        self.autostart = gtk.MenuItem(label)
        self.autostart.connect('activate',self.toggle_auto_startup)
        self.app_menu.append(self.autostart)
        self.autostart.show()

        self.open_gnome_disks = gtk.MenuItem('Open Disks Utility')
        self.open_gnome_disks.connect('activate',self.open_disks_utility)
        self.app_menu.append(self.open_gnome_disks)
        self.open_gnome_disks.show()

        self.quit_app = gtk.MenuItem('Quit')
        self.quit_app.connect('activate', self.quit)
        self.app_menu.append(self.quit_app)
        self.quit_app.show()

        self.app.set_menu(self.app_menu)

    def mount_partition(self,*args):
        # TODO: implement error checking for mounting
        return self.run_cmd(['udisksctl','mount','-b','/dev/' + args[-1]])

    def get_mountpoint_usage(self,mountpoint):
        fs = statvfs(mountpoint)
        usage = 100*(float(fs.f_blocks)-float(fs.f_bfree))/float(fs.f_blocks)
        return str("{0:.2f}".format(usage))

    def get_partitions(self):
        objects = self.get_dbus('system', 
                           'org.freedesktop.UDisks2', 
                           '/org/freedesktop/UDisks2', 
                           'org.freedesktop.DBus.ObjectManager',
                           'GetManagedObjects',
                           None)


        partitions = []
        for item in objects:
            try:
                if 'block_devices'  in str(item):


                       drive = self.get_dbus_property('system',
                                        'org.freedesktop.UDisks2',
                                        item,
                                        'org.freedesktop.UDisks2.Block',
                                        'Drive')
                       if drive == '/': continue

                       mountpoint = self.get_mountpoint(item)
                       if not mountpoint: continue
                       mountpoint = mountpoint.replace('\x00','')

                       drive = str(drive).split('/')[-1]
                       usage = self.get_mountpoint_usage(mountpoint)

                       part = str(item.split('/')[-1])
                       partitions.append((part,drive,mountpoint,usage))                       

            except Exception as e:
                #print(e)
                pass

        # returning list of tuples
        partitions.sort()
        return partitions

    def get_mountpoint(self,dev_path):
        try:
            data = self.get_dbus_property(
                             'system',
                             'org.freedesktop.UDisks2',
                             dev_path,
                             'org.freedesktop.UDisks2.Filesystem',
                             'MountPoints')[0]

        except Exception as e:
            #print(e)
            return None
        else:
            if len(data) > 0:
                return ''.join([ chr(byte) for byte in data])


    def get_unmounted_partitions(self):
        objects = self.get_dbus('system', 
                           'org.freedesktop.UDisks2', 
                           '/org/freedesktop/UDisks2', 
                           'org.freedesktop.DBus.ObjectManager',
                           'GetManagedObjects',
                           None)


        partitions = []
        for item in objects:
            try:
                if 'block_devices'  in str(item):
                       drive = self.get_dbus_property('system',
                                        'org.freedesktop.UDisks2',
                                        item,
                                        'org.freedesktop.UDisks2.Block',
                                        'Drive')
                       if drive == '/': continue

                       mountpoint = self.get_mountpoint(item)
                       if  mountpoint: continue

                       drive = str(drive).split('/')[-1]
                       part = str(item.split('/')[-1])
                       if not part[-1].isdigit(): continue
                       partitions.append((part,drive))                       
                       #print(partitions)

            except Exception as e:
                #print(e)
                pass

        partitions.sort()
        return partitions

    def get_dbus(self,bus_type,obj,path,interface,method,arg):
        if bus_type == "session":
            bus = dbus.SessionBus() 
        if bus_type == "system":
            bus = dbus.SystemBus()
        proxy = bus.get_object(obj,path)
        method = proxy.get_dbus_method(method,interface)
        if arg:
            return method(arg)
        else:
            return method()

    def get_dbus_property(self,bus_type,obj,path,iface,prop):

        if bus_type == "session":
           bus = dbus.SessionBus()
        if bus_type == "system":
           bus = dbus.SystemBus()
        proxy = bus.get_object(obj,path)
        aux = 'org.freedesktop.DBus.Properties'
        props_iface = dbus.Interface(proxy,aux)
        props = props_iface.Get(iface,prop)
        return props

    def make_alias(self,*args):
        partitions = [ i[0] for i in self.get_partitions() ]

        combo_values = '|'.join(partitions)
        #print(combo_values)
        command=[ 'zenity','--forms','--title','Make Alias',
                  '--add-combo','Partition','--combo-values',
                  combo_values,'--add-entry','Alias'    ]        
        user_input = self.run_cmd(command)
        if not user_input: return

        alias = user_input.decode().strip().split('|')

        existing_values = None

        if os.path.isfile(self.config_file):
            with open(self.config_file) as conf_file:
                try:
                    existing_values = json.load(conf_file)
                except ValueError:
                    pass


        with open(self.config_file,'w') as conf_file:
             if existing_values:
                 existing_values[alias[0]] = alias[1]
             else:
                 existing_values = {alias[0]:alias[1]}

             #print(existing_values)
             json.dump(existing_values,conf_file,indent=4,sort_keys=True)


    def find_alias(self,part):
        if os.path.isfile(self.config_file):
            with open(self.config_file) as conf_file:
                try:
                    aliases = json.load(conf_file)
                except ValueError:
                    pass
                else:
                    if part in aliases:
                       return aliases[part]
                    else:
                       return None

    def toggle_auto_startup(self,*args):
        user_home = os.path.expanduser('~')
        desktop_file = '.config/autostart/udisks-indicator.desktop'
        full_path = os.path.join(user_home,desktop_file)

        if os.path.exists(full_path):
           os.unlink(full_path)
        else:
           original = '/usr/share/applications/udisks-indicator.desktop'
           if os.path.exists(original):
               shutil.copyfile(original,full_path)

        self.make_menu()


    def open_mountpoint(self,*args):
        pid = subprocess.Popen(['xdg-open',args[-1]]).pid

    def open_disks_utility(self,*args):
        pid = subprocess.Popen(['gnome-disks']).pid

    def run_cmd(self, cmdlist):
        """ Reusable function for running external commands """
        new_env = dict(os.environ)
        new_env['LC_ALL'] = 'C'
        try:
            stdout = subprocess.check_output(cmdlist, env=new_env)
        except subprocess.CalledProcessError:
            pass
        else:
            if stdout:
                return stdout

    def run(self):
        """ Launches the indicator """
        try:
            gtk.main()
        except KeyboardInterrupt:
            pass

    def quit(self, data=None):
        """ closes indicator """
        gtk.main_quit()

def main():
    """ defines program entry point """
    indicator = UdisksIndicator()
    indicator.run()

if __name__ == '__main__':
    main()

/usr/share/applications/udisks-indicator.desktop

[Desktop Entry]
Version=1.0
Name=Udisks Indicator
Comment=Indicator for reporting partition information
Exec=udisks-indicator
Type=Application
Icon=drive-harddisk-symbolic.svg
Terminal=false

ข้อมูลเพิ่มเติม:

การทดสอบ Ubuntu Mate 16.04:

ป้อนคำอธิบายรูปภาพที่นี่

ผู้ใช้ Gnome ต้องการส่วนขยาย (การสนับสนุน KStatusNotifierItem / AppIndicator) เพื่อให้ตัวบ่งชี้ทำงานได้อย่างถูกต้อง:

ป้อนคำอธิบายรูปภาพที่นี่


1
สามารถยืนยันได้ ใช้งานได้กับ Xfce4 ทำได้ดีมาก! =)
Terrance

@Terrance ในกรณีที่คุณต้องการคว้าเวอร์ชันล่าสุดให้ดูการอัปเดตคำตอบ Zach ทดสอบ Xfce ของเขาแล้วเช่นกันบอกว่ามันใช้งานได้ดี
Sergiy Kolodyazhnyy

เย็น! ขอบคุณที่ทำให้ฉันรู้. ฉันจะให้มันหมุนวน =) อัปเดต: ดูดีจริงๆและฉันชอบไอคอนที่คุณเปลี่ยนแปลง ทำได้ดี! =)
Terrance

+1 แต่ควรชี้ให้เห็นว่า "กำลังจะออก PPA เร็ว ๆ นี้" หรือไม่
WinEunuuchs2Unix

@ WinEunuuchs2Unix ใช่สามารถลบออกได้ คำตอบและตัวบ่งชี้นี้ต้องการการอัปเดตที่ยิ่งใหญ่ แต่เมื่อเร็ว ๆ นี้ไม่มีเวลา
Sergiy Kolodyazhnyy


1

มีคำตอบอีกข้อหนึ่งที่ใช้ตัวบ่งชี้ Sysmonitorขั้นพื้นฐานแต่คุณสามารถสร้างพาเนลที่กำหนดเองของคุณเองด้วยข้อมูลได้มากเท่าที่คุณต้องการ

Google (ค้นหาอย่างน้อยก็) เป็นเพื่อนของคุณ

ขั้นแรกคือการหาวิธีคำนวณเปอร์เซ็นต์การใช้งานพาร์ติชัน :

$ percentage=($(df -k --output=pcent /dev/sda1))
$ echo "${percentage[1]}"
13%

สร้างสคริปต์ทุบตีเพื่อสะท้อนไปยังแผง

นี่เป็นสคริปต์ทุบตีเพื่อใช้เป็น "กำหนดเอง" ตัวเลือกในSysmonitor ดัชนี มันจะแสดงเปอร์เซ็นต์ที่ใช้กับสามพาร์ติชั่นแรกใน/dev/sda:

#!/bin/bash
echo "sda1: "
percentage=($(df -k --output=pcent /dev/sda1))
echo "${percentage[1]}"
echo " | sda2: "
percentage=($(df -k --output=pcent /dev/sda2))
echo "${percentage[1]}"
echo " | sda3: "
percentage=($(df -k --output=pcent /dev/sda3))
echo "${percentage[1]}"

ตัวอย่างผลลัพธ์

เมื่อใช้งานจะมีลักษณะเช่นนี้:

ตัวบ่งชี้ systmonitor example.png

ติดตั้งและกำหนดค่าสคริปต์ที่กำหนดเองในตัวบ่งชี้ Sysmonitor

สำหรับคำแนะนำโดยละเอียดเกี่ยวกับการติดตั้งตัวบ่งชี้ Sysmonitorและการกำหนดสคริปต์ที่กำหนดเองดูคำตอบนี้: BASH สามารถแสดงใน systray เป็นตัวบ่งชี้แอปพลิเคชันได้หรือไม่?


ทางออกที่น่ารัก แม้ว่าอาจมีความยาวขึ้นด้วยพาร์ติชั่นและอุปกรณ์จำนวนมาก
Sergiy Kolodyazhnyy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.