จะหยุด gedit (และโปรแกรมอื่น ๆ ) ไม่ให้แสดงคำเตือนของ GTK และสิ่งอื่น ๆ ในหน้าจอเทอร์มินัลของฉันได้อย่างไร?


32

ฉันเรียกใช้ตัวจัดการหน้าต่างที่ยอดเยี่ยมด้วยความไว้วางใจหลังจากอัพเกรดจากคำราม สภาพแวดล้อมเดสก์ท็อปของฉันโดยเจตนาไม่มี Gnome / Freedesktop daemons ทั้งหมดที่ทำงานอยู่ - ฉันไม่ต้องการ

เมื่อฉันรันgeditจาก terminal เช่นนี้

gedit file

มันแสดงข้อความเช่นนี้ไปทั่วเทอร์มินัลของฉันเมื่อใดก็ตามที่ฉันกด Enter หรือบันทึกหรือในโอกาสอื่น ๆ :

(gedit:5700): Gtk-WARNING **: Calling Inhibit failed: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.gnome.SessionManager was not provided by any .service files

ฉันเข้าใจความหมายของคำเตือนนี้และฉันตัดสินใจว่ามันไม่สำคัญสำหรับฉัน

ฉันจะปิดคำเตือนประเภทนี้ได้อย่างไร โดย "ปิด" ฉันไม่ได้หมายถึงวิธีการแก้ปัญหาเหล่านี้หรือสิ่งที่คล้ายกัน:

  • ท่อส่งออกของ gedit เป็น /dev/null
  • การเขียนสคริปต์ wrapper ที่ไพพ์เอาต์พุตของ gedit ลงใน /dev/null
  • สร้างนามแฝงที่ท่อส่งออกของ gedit เป็น /dev/null

วิธีแก้ไขปัญหาเหล่านี้ไม่สามารถยอมรับได้เนื่องจากต้องใช้แยกต่างหากสำหรับแต่ละแอปพลิเคชัน Gnome - gedit ไม่ใช่สิ่งเดียวที่ชอบรบกวนเทอร์มินัล


2
ทำไมคุณไม่สามารถใช้ 3 ตัวเลือกที่คุณกล่าวถึง
ทิม

ฉันไม่คิดว่าคุณสามารถปิดคำเตือนเหล่านั้นได้ แต่ตามที่ @Tim ถามคุณมีข้อผิดพลาดอะไรบ้างในการใช้ 3 ตัวเลือกที่จะแก้ปัญหาของคุณ
ElefantPhace

7
ขอบคุณฉันรู้วิธีการเปลี่ยนเส้นทางของเชลล์ เหตุผลที่ฉันไม่ต้องการทำสิ่งนี้ (และระบุอย่างชัดเจน) ว่าคำเตือนเหล่านี้ยังปรากฏในโปรแกรมอื่น ๆ อีกมากมาย ตัวเลือกการกำหนดค่าสำหรับ dbus หรือส่วนประกอบใด ๆ ที่สร้างคำเตือนเหล่านี้จะปิดคำเตือนสำหรับโปรแกรมทั้งหมดที่สร้างขึ้น ด้วยการเปลี่ยนเส้นทางฉันต้องใช้วิธีแก้ปัญหา (ซึ่งไม่ใช่วิธีแก้ปัญหา) กับแต่ละโปรแกรม
FUZxxl

@FUZxxl ฉันไม่สามารถรับ gedit เพื่อส่งออกข้อผิดพลาดอย่างสม่ำเสมอ แต่ฉันอยากรู้ว่าexport GCONF_DEBUG="no"จะทำอะไร
แดน

@ dan08 ไม่ไม่ได้ทำเคล็ดลับ
FUZxxl

คำตอบ:


17

ครั้งแรกฉันยังพบว่ามันน่ารำคาญที่คำเตือนเหล่านี้ปรากฏบน Ubuntu ออกโดยไม่มีวิธีการ "ที่เหมาะสม" เพื่อปิดการใช้งานซึ่งฉันสามารถหาได้gir1.2-gtksource-3.0ซึ่งดูเหมือนว่าจะใช้งานไม่ได้ตั้งแต่ติดตั้งไปแล้วหรือไม่สนใจ - แต่ฉันต้องการระงับพวกเขาอย่างสมบูรณ์เพราะมันทำให้เครื่องส่งเสียงรบกวนของฉัน)

ฉันมาพร้อมกับรหัสต่อไปนี้ซึ่งดูเหมือนว่าจะประพฤติตามที่ฉันคาดหวังไว้และขึ้นอยู่กับคำตอบของ TuKsn แต่ก็ปรับปรุงให้ดีขึ้นเล็กน้อย:

  • ทำงานตามค่าเริ่มต้น ( gedit ...) โดยไม่จำเป็นต้องใช้ F12 หรือทางลัดอื่น ๆ (เพื่อเรียกใช้งานที่ไม่มีการกรอง/usr/bin/gedit ... )
  • แสดงชื่อคำสั่งที่ป้อนเมื่อเลิกใช้เป็นงานพื้นหลัง

ยังคงสามารถวางนัยให้เป็นบิตได้ แต่ตอนนี้ถ้าคุณต้องการการรักษาที่เหมือนกันสำหรับคำสั่งอื่นให้ทำซ้ำgedit()ฟังก์ชั่นสำหรับชื่อคำสั่งซึ่งต้องใช้ตัวกรองเดียวกัน

# solution adapted from: http://askubuntu.com/questions/505594
# TODO: use a list of warnings instead of cramming all of them to a single grep.
# TODO: generalize gedit() to allow the same treatment for several commands
#       without duplicating the function with only a different name
# output filter. takes: name_for_history some_command [arguments]
# the first argument is required both for history, but also when invoking to bg
# such that it shows Done <name> ... instead of e.g. Done /usr/bin/gedit ...
suppress-gnome-warnings() {
    # $1 is the name which should appear on history but is otherwise unused.
    historyName=$1
    shift

    if [ -n "$*" ]; then
        # write the real command to history without the prefix
        # syntax adapted from http://stackoverflow.com/questions/4827690
        history -s "$historyName ${@:2}"

        # catch the command output
        errorMsg=$( $* 2>&1 )

        # check if the command output contains not a (one of two) GTK-Warnings
        if ! $(echo $errorMsg | grep -q 'Gtk-WARNING\|connect to accessibility bus'); then
            echo $errorMsg
        fi
    fi
}
gedit() {
  suppress-gnome-warnings $FUNCNAME $(which $FUNCNAME) $@
}

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

# generates a function named $1 which:
# - executes $(which $1) [with args]
# - suppresses output lines which match $2
# e.g. adding: _supress echo "hello\|world"
# will generate this function:
# echo() { $(which echo) "$@" 2>&1 | tr -d '\r' | grep -v "hello\|world"; }
# and from now on, using echo will work normally except that lines with
# hello or world will not show at the output
# to see the generated functions, replace eval with echo below
# the 'tr' filter makes sure no spurious empty lines pass from some commands
_supress() {
  eval "$1() { \$(which $1) \"\$@\" 2>&1 | tr -d '\r' | grep -v \"$2\"; }"
}

_supress gedit          "Gtk-WARNING\|connect to accessibility bus"
_supress gnome-terminal "accessibility bus\|stop working with a future version"
_supress firefox        "g_slice_set_config"

นี่คือคำตอบที่ดี ฉันจะใช้สิ่งนี้ในอนาคต
FUZxxl

2

มันเป็นวิธีการแก้ปัญหา แต่คุณไม่จำเป็นต้องใช้มันกับทุกแอปพลิเคชัน

เขียนสิ่งนี้ให้กับคุณ.bashrcและคุณสามารถใช้ wrapper นี้กับ F12 (หรือเลือกคีย์อื่น) เพื่อยับยั้งการเตือน:

# output filter
of() { 
    if [ -n "$*" ]; then   
        # write the real command to history without the prefix "of" 
        history -s "$*"

        # catch the command output
        errorMsg=$( $* 2>&1 )

        # check if the command output contains not a GTK-Warning
        if ! $(echo $errorMsg | grep -q 'Gtk-WARNING'); then
            echo $errorMsg 
        fi
    fi
}

# write the function "of" before every command if the user presses F12
bind '"\e[24~": "\e[1~ of \e[4~\n"'

ดูดีขึ้นเล็กน้อย ฉันจะทดสอบสิ่งนั้น
FUZxxl

1

ฉันเขียนเครื่องมือซ่อนคำเตือนใน C ซึ่งฉันใช้งานง่ายกว่าสคริปต์ที่แสดงด้านบน นอกจากนี้ยังจะเขียนเอาต์พุตทั้งหมดที่เขียนไปstdoutตามค่าเริ่มต้น (เนื่องจาก Gtk และคำเตือนอื่น ๆ ถูกส่งไปที่stderrจึงstderrไม่แยกวิเคราะห์stdoutตามค่าเริ่มต้น)

ปัญหาใหญ่อย่างหนึ่งของสคริปต์ด้านบนคือมันจะไม่เขียนอะไรลงบนคอนโซลของคุณแม้ว่ามันจะไม่ตรงกับ regex จนกว่าจะเสร็จ นี่เป็นเพราะมันบันทึกข้อมูลทั้งหมดในตัวแปรแล้ว grep ตัวแปรนั้นเมื่อทำเสร็จแล้ว นอกจากนี้ยังหมายความว่ามันจะบันทึกผลลัพธ์ในตัวแปรที่อาจใช้หน่วยความจำจำนวนมาก (อย่างน้อยคุณควรบันทึกไว้ในไฟล์ชั่วคราว) ในที่สุดจากสิ่งที่ฉันเห็น, grep จะป้องกันการแสดงผลใด ๆ หากหนึ่งบรรทัดที่ตรงกัน . อาจไม่ใช่สิ่งที่คุณต้องการ

เครื่องมือนี้สามารถใช้ในนามแฝงง่ายๆดังนี้:

alias gvim="hide-warnings gvim"

(ฉันใช้gvim... ฉันแน่ใจว่ามันจะทำงานด้วยgeditเช่นกัน)

ไฟล์มีอยู่ในตัวเองไม่มีการพึ่งพานอกเหนือจากไลบรารี C ดังนั้นคุณสามารถรับสำเนาและรวบรวมและติดตั้งได้อย่างง่ายดาย:

gcc hide-warnings.c -o hide-warnings
sudo cp hide-warnings /usr/bin/.

มีเอกสารเพิ่มเติมบางอย่างในไฟล์และคุณสามารถใช้--helpเมื่อรวบรวมสำหรับเอกสารฉบับย่อ

เวอร์ชันที่ใหม่กว่าซึ่งในบางจุดจะใช้ประโยชน์จากไลบรารี advgetopt อยู่ใน C ++


ลิงค์ตาย
Armin Rigo

@ArminRigo, Ah! มันเคลื่อนไหว ที่นี่ฉันใส่ลิงค์ใหม่ไปที่ล่าสุดก่อนที่จะย้ายเพราะตอนนี้มันเป็น C ++ นอกจากนี้ยังมีลิงก์ไปยังเวอร์ชัน C ++ เวอร์ชั่น C จะไม่เปลี่ยนแปลงอีกต่อไป
Alexis Wilke

0

ฉันกำลังหายูทิลิตีเพื่อแก้ไขปัญหานี้ด้วยตัวเอง

ปัญหาของฉันกับคำตอบที่ให้มีดังนี้:

  • เป็นสิ่งสำคัญที่ stdout และ stderr จะไม่ถูกรวมเข้าในสตรีมเดียว
  • ฉันไม่สามารถเรียกใช้คำสั่งกรองเอาท์พุททั้งหมดจนกว่ามันจะยุติและพิมพ์ในตอนท้าย (เช่นวิธีการแก้ปัญหาจะต้องสตรีมเอาท์พุทอย่างถูกต้อง)
  • ฉันต้องการรักษาลำดับของข้อความ stdout และ stderr ให้มากที่สุด

ฉันซาบซึ้งในความพยายามที่ฉันได้เห็นด้วย Bash อย่างไรก็ตามฉันล้มเหลวในการระบุวิธีการแก้ปัญหาที่บรรลุเงื่อนไขทั้งสามข้อที่กล่าวถึงข้างต้น

ทางออกสุดท้ายของฉันเขียนใน NodeJS ซึ่งฉันเข้าใจว่าจะไม่ถูกติดตั้งในกล่อง linux จำนวนมาก ก่อนที่จะเลือกที่จะเขียนเวอร์ชั่น JS ฉันพยายามที่จะเขียนโค้ดในไพ ธ อนและพบว่าไลบรารี async IO ค่อนข้างน่าเกลียดและแตกจนรุ่นล่าสุดของไพ ธ อน (~ 3.5 ซึ่งวางจำหน่ายแล้วใน Sros distros รุ่นใหม่)

การลดการพึ่งพาเป็นเหตุผลเพียงอย่างเดียวในการเลือกไพ ธ อนดังนั้นฉันจึงละทิ้งมันสำหรับ NodeJS ซึ่งมีชุดของห้องสมุดที่น่าทึ่งสำหรับ IO ในระดับที่ค่อนข้างต่ำ async-oriented

นี่มันคือ:

#!/usr/bin/env nodejs

const spawn = require('child_process').spawn

function usage() {
    console.warn('Usage: filter-err <error regex> <cmd> [<cmd arg> ...]')
    process.exit(1)
}

function main(err_regex, cmd_arr) {
    let filter = new RegExp(err_regex)

    let proc = spawn(cmd_arr[0], cmd_arr.slice(1), {
        shell: true,
        stdio: ['inherit', 'inherit', 'pipe']
    })

    proc.stderr.on('data', (err) => {
        err = err.toString('utf8')

        if (! err.match(filter))
            process.stderr.write(err)
    })

    proc.on('close', (code) => process.exit(code))
}

const argv = process.argv

if (argv.length < 4)
    usage()
else
    main(argv[2], argv.slice(3))

หากต้องการใช้สคริปต์นี้คุณอาจเพิ่มบรรทัดเหล่านี้ใน. bashrc ของคุณ:

alias gimp='filter-err "GLib-[^ ]*-WARNING" gimp'

กระบวนการย่อยที่คุณเลือกเรียกใช้จะสืบทอด stdin ดังนั้นคุณสามารถใช้ BASH ไพพ์หรือการเปลี่ยนเส้นทางได้อย่างอิสระ

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