我寫了一個類來生成一個 shell(在一個 Electron 應用程式中)并與之互動,如下所示:
const { spawn } = require('child_process')
class Shell {
constructor() {
this.process = spawn('/bin/bash', []);
this.process.stdout.on('data', (data) => {
const out = data.toString()
console.log('stdout:', out)
if (this.res) {
this.res(out)
}
});
this.process.stderr.on('data', function (data) {
const err = data.toString()
console.log('stderr:', err)
if (this.rej) this.rej(err)
});
}
send(command, throwErr = false) {
return new Promise((resolve, reject) => {
this.res = resolve
if (throwErr) this.rej = reject
else this.rej = resolve
this.process.stdin.write(command '\n')
})
}
}
我得到的輸出是這樣的:
stdout: ]0;student@linux-opstation-jyrf: ~[01;32mstudent@linux-opstation-jyrf[00m:[01;34m~[00m$
這是我使用 JSON 對輸出進行字串化以查看轉義字符的版本: stdout: "\u001b]0;student@linux-opstation-jyrf: ~\u0007\u001b[01;32mstudent@linux-opstation-jyrf\u001b[00m:\u001b[01;34m~\u001b[00m$ ssh -t -t -oStrictHostKeyChecking=no [email protected]\r50.30.231\r\n"
我意識到這些是來自用于格式化的 bash 轉義序列的工件,我無法弄清楚如何擺脫它,特別是因為沒有列印轉義字符。
編輯:所以我將原始標準輸出Buffer(data在代碼中)寫入二進制檔案:
fs.createWriteStream(path, { encoding: 'binary'}).write(data);
并發現該方法中似乎沒有發生任何損失.toString()(我認為?)所以我在撓頭,其余的標準輸出標記被截斷。
00000000: 1b5d 303b 7374 7564 656e 7440 6c69 6e75 .]0;student@linu
00000010: 782d 6f70 7374 6174 696f 6e2d 6a79 7266 x-opstation-jyrf
00000020: 3a20 7e07 1b5b 3031 3b33 326d 7374 7564 : ~..[01;32mstud
00000030: 656e 7440 6c69 6e75 782d 6f70 7374 6174 ent@linux-opstat
00000040: 696f 6e2d 6a79 7266 1b5b 3030 6d3a 1b5b ion-jyrf.[00m:.[
00000050: 3031 3b33 346d 7e1b 5b30 306d 2420 7373 01;34m~.[00m$ ss
00000060: 6820 2d74 202d 7420 2d6f 5374 7269 6374 h -t -t -oStrict
00000070: 486f 7374 4b65 7943 6865 636b 696e 673d HostKeyChecking=
00000080: 6e6f 2073 7475 6465 6e74 4031 302e 350d no [email protected].
00000090: 3530 2e33 302e 3233 310d 0a 50.30.231..
但也許我在保存檔案時沒有得到正確的編碼,因為我認為原始緩沖區應該(?)像這樣輸出文本\u001b[00m:\u001b[01;34m并且\uFFFF十六進制字符不在那里。編輯:啊,\uFFFF顯然是unicode。仍在弄清楚如何將該緩沖區正確保存為二進制檔案,我認為 unicode 正在丟失,而{encoding: 'binary'}set 作為選項。否則十六進制轉儲僅顯示 utf8,這聽起來更有可能。
uj5u.com熱心網友回復:
假設這些工件確實來自自定義的提示字串,最簡單的方法是更改??提示字串。對此有多種選擇,這在一定程度上取決于設定提示字串的位置。
如果您根本收到提示,則bash它作為互動式 shell 運行。它不會使用您用來啟動它的命令作為登錄 shell 運行。因此,相關的初始化步驟如下:
當一個不是登錄 shell 的互動式 shell 啟動時,bash 讀取并執行來自 的命令
~/.bashrc(如果該檔案存在)。這可以通過使用--norc選項來禁止。該--rcfilefile選項將強制bash的讀取和檔案,而不是執行命令~/.bashrc。
(Bash 手冊頁)
因此,您可以將--norc選項傳遞bash給禁止讀取任何 shell 初始化檔案,從而獲得默認提示(以及其他所有內容)。但是該環境對于您的需求來說可能過于稀疏,因此作為替代方案,您可以創建一個專用的 shell 組態檔來設定您想要的確切配置,并使用該--rcfile選項讓bash您的程式啟動的實體使用它。 這可能是您的最佳選擇,但可能需要一些作業才能根據需要進行設定。
作為一種更快更臟的替代方法,您可以修改相關內容~/.bashrc以更改提示字串(洗掉PS1and 的定義PS2,或者將它們重新定義為默認值: PS1='\s-\v\$ ' PS2='> ')。您還可以將前兩個與讀取默認組態檔并覆寫提示字串的自定義組態檔結合起來:
電子檔案
. ~/.bashrc
PS1='\s-\v\$ '
PS2='> '
uj5u.com熱心網友回復:
這是一個笨拙、丑陋、快速骯臟的解決方案。我歡迎更優雅的方法:
const { spawn } = require('child_process')
class Shell {
constructor() {
// I just threw a bunch of output into a regex tester
// and wrote `|` joined matches until all markup in my
// sample input was detected. That's all there is to it.
// This will almost certainly not work across various
// machines depending on how the markup is structured.
const re = /\\u[0-9 a-f]{4}\[\d\d;\d\dm|\\u[0-9 a-f]{4}]0;|\\u[0-9 a-f]{4}\[\d\dm:\\u[0-9 a-f]{4}\[\d\d;\d\dm|\\u[0-9 a-f]{4}\[\d\dm|\\u[0-9 a-f]{4}/g
this.process = spawn('/bin/bash', []);
this.process.stdout.on('data', (data) => {
const out = data.toString()
const stringified = JSON.stringify(out)
console.log('stdout:', stringified)
const trimmed = stringified.replace(re, "")
.split('"').join('')
.split('\\r').join('')
.split('\\n').join('')
console.log('parsed stdout:', trimmed)
if (this.res) {
this.res(out)
}
});
this.process.stderr.on('data', function (data) {
const err = data.toString()
console.log('stderr:', err)
if (this.rej) this.rej(err)
});
}
send(command, throwErr = false) {
return new Promise((resolve, reject) => {
this.res = resolve
if (throwErr) this.rej = reject
else this.rej = resolve
this.process.stdin.write(command '\n')
})
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/323862.html
上一篇:無法在控制器中獲取異步函式的結果
