deepin-terminal改造風雲再起


1. 創作背景

使用deepin-terminal的時候,我發現一些小的問題。

在論壇的帖子(https://bbs.deepin.org/zh/post/224502)也總結反饋了這些問題

  • 終端標簽變色
  • 遠程管理標簽標題跟右鍵選項顯示異常
  • 截圖發送到微信之后,再切換到終端時,雙擊復制無法將內容置入剪切板

經過我虛擬機全新安裝deepin20.2.3后,幾輪測試下來發現

終端標簽變色的問題,應該只是個特性,發生在如果標簽1有工作正在進行,或者有更新,比如sudo apt update或者ssh 連接超時被close時,而此時你正在標簽2工作,那么這個變色會提醒你,標簽1的工作結束了,或者有更新

截圖發送到微信,然后切換到終端,雙擊復制,概率性無法復制的問題,應該是個穩定的bug。這個bug我也反饋給官方了,不清楚是否后續會解決。

今天來說的是遠程管理

2. 遠程管理的bug描述

deepin-terminal提供的遠程管理,一般會要求我們輸入名稱,地址 ,帳號,密碼這些。正常情況下,如果這些都是正常的,遠程連接不會存在問題。連接上以后,標簽標題會變成遠程主機的用戶@主機名,而終端右鍵也出現“上傳文件”和“下載文件“的選項。

正常的情況我們就不說了,說說不正常的情況

2.1 點擊遠程連接時,突然不想連接了,或者密碼錯誤了,ctrl+c終止連接失敗

這種情況發生在,比如管理員重新設置了遠程連接的密碼,而你的遠程連接並未更新,那么你使用這個連接遠程主機時,必然會提示你輸入密碼,3此輸入不正確,那么就無法登陸。如果你輸入1次,發現不正確,直接ctrl+c了,那么此時標簽的標題已經被設置為遠程主機的主機名@主機地址了,而右鍵選項也多出了“上傳文件”和“下載文件”的選項。

在未成功登陸遠程主機的情況下,這種顯示的變化,顯然是個BUG。如何解決,且等下文分析

2.2 輸錯了服務器的IP,因為網絡路由不正確,連接失敗

如果你不小心直接輸錯了遠程主機的IP地址,而且點擊登陸時發現根本沒法登陸,報一些比如No route to host的信息,告訴你沒有到遠程主機的路由。而此時標簽的標題已經被設置為遠程主機的主機名@主機地址了,而右鍵選項也多出了“上傳文件”和“下載文件”的選項。

在未成功登陸遠程主機的情況下,這種顯示的變化,顯然是個BUG。如何解決,且等下文分析

2.3 修改了ssh配置文件,比如修改了LogLevel導致退出遠程主機后顯示異常

如果你是一個不喜歡被繁雜的信息打擾的人,修改了/etc/ssh/ssh_config里面,把LogLevel設置為quit,那么當你使用deepi-terminal的遠程管理登陸遠程主機時,標簽標題和右鍵選項均可以正常顯示,但是你工作結束,通過exit命令,logout命令或者直接ctrl+d登出時,你會發現你的標簽和右鍵選項還在。

在成功退出遠程主機后,終端標簽標題跟右鍵選項沒有變化,這顯然是個BUG。如何解決,且等下文分析

3. 如何解決

具體的解決,肯定是要修改代碼的啦

3.1 先分析一下為何如此

分析deepin-terminal的源碼得知,當你使用遠程管理登陸遠程節點時,deepi-terminal實際上載入和執行了一段標准的expect腳本,該腳本是一個免交互的腳本。deepin-terminal會把遠程管理面板里面的信息同步到這段expect里面,替換到設置的“宏”,然后執行它們。

同時deepin-terminal啟動了一個定時器觸發,0.1s的時間,判斷這個遠程管理是否存在expect的進程信息,如果有就把當前標簽的連接,設置為遠程標簽的格式,還有其他信息,比如編碼,和右鍵選項。

試想,如果expect執行的ssh超時還沒有到,標簽已經變化,而ssh連接失敗后,變化的標簽會變回去嗎?

答案是不一定的。這就是上面的2.1和2.2描述的bug原因。

至於2.3的描述,就要看deepin-terminal退出遠程時,是如何把標簽重新設置為本地的。它是通過截獲收發數據的字符串,判斷其是否包含"Connected to "和"closed."或者"Permission denied"來判斷終端斷開了遠程連接。

inline void TermWidget::onTermWidgetReceivedData(QString value)
{
    /******** Modify by ut000610 daizhengwen 2020-05-25: quit download****************/
    if (value.contains("Transfer incomplete")) {
        QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_C, Qt::ControlModifier);
        QApplication::sendEvent(focusWidget(), &keyPress);
    }    
    if (value.endsWith("\b \b #")) {                     // 結束的時候有亂碼的話,將它清除
        QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_U, Qt::ControlModifier);
        QApplication::sendEvent(focusWidget(), &keyPress);
    }    
    /********************* Modify by ut000610 daizhengwen End ************************/
    // 退出遠程后,設置成false
    if ((value.contains("Connection to") && value.contains(" closed.")) || value.contains("Permission denied"))
        QTimer::singleShot(100, this, &TermWidget::onExitRemoteServer);
}

而我修改了LogLevel為quit,這個配置在我登出遠程節點時,只顯示Logout或者中文“登出”,”注銷“等字樣,並不存在”Connection to"的字樣,因此終端就認定這個操作不是退出遠程,自然它的標簽標題跟右鍵菜單是不會變化的了。

3.2 再看看如何處理

直接看修改結果吧,對於2.1和2.2的bug描述,直接修改源碼文件:deepin-terminal/src/assets/other/ssh_login.sh

修改為:

# Spawn and expect
if { $authentication == "no" } {
eval spawn $ssh_cmd $ssh_opt -t $remote_command exec \\\$SHELL -l
} else {
eval spawn $ssh_cmd $ssh_opt -i $private_key -t $remote_command exec \\\$SHELL -l
}


#fix bug:修復在登陸過程中直接ctlr+c終止登陸時,終端標簽和右鍵選項變成遠程的現象.
trap {
    send_user "Connection to closed.\n"
    exit
} SIGINT

if { [string length $password] } {
    expect {
        timeout {send_user "ssh connection time out, please operate manually\n"}
        -nocase "yes/no" {send "yes\r"; exp_continue}
        -nocase -re "password:|enter passphrase for key" { send "$encoded_password\r" }
        "No route to host" { send "Connection to closed.\n";exp_continue} #修改遠程地址錯誤導致的終端標簽和右鍵選項變成遠程
        "Connection to closed." { exit }
    }
}

interact

大概意思就是通過expect捕獲2.1和2.2描述的bug或者crtl+c信號,向終端拋出"Connection to closed."字樣,讓終端捕獲這個字樣后,把當前標簽設置為本地標簽即可,就不會顯示為遠程的樣式了

而對於2.3的bug描述,還是修改/etc/ssh/ssh_config的LogLevel參數吧,修改為LogLevel=ERROR即可,另外一種動作比較大就是修改源碼,把"登出",“注銷”,"logout"等字樣包含在對終端退出遠程的判斷,不過這個成本比較大了,意義也不是很大。暫且不做了。

4. 總結

花了2天時間摸索和測試吧,總的來說,達到了驗證,修改和修復這些bug的目的。估計沒有多少人會觸發這樣的bug,但是至少可以學習deepin-terminal的工作原理不是,賺到了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM