各タブの実行を開始するコマンドを受け入れるマルチタブ端末はありますか?

各タブの実行を開始するコマンドを受け入れるマルチタブ端末はありますか?

私の目標は、マルチ端末環境を起動することです。

  • キーボードキーを押すのと同じように、一度にすべての端末に簡単にアクセスできます(yakuakeとguakeを使用してこれを行うことができます)。
  • アイテムがどこにあるかを知るために、カスタム名の付いたタブ
  • 事前に実行された完全なコマンドでマルチタップ端末を実行することで、各タップ端末に完全な設定環境を提供できます。

今日は何をしますか?
guakeを開きましたが、yakuakeよりもRAMを少なく使います。
F5などのキーを押して開発の基本環境を開始できるように、Bashにはいくつかのキーバインディングが設定されているため、特定の端末ごとにF5を押す必要があります。
それでも、5つのタブのそれぞれに特定のコマンドを入力する必要があります。
また、どの特定のコマンドを実行するかを知るために、以前に名前を付けました。

研究:

  • マルチタップ端子:ヤクアケ、グアケ、ミスターxvt
  • 名前変更可能なタブ:guake、yakuake。しかし、mrxvtの方法が見つかりません。
  • 私たちが使用できることを知っていますバス タブ名の変更など、yakuakeを使用して多くの操作を実行できます。 guacについてよくわかりません。 mrxvtを使用してタブ名を変更する方法が見つかりません。

最終結果を得るには、間接的な方法(コマンドラインを必要とせずにqdbusを介して行うことができます)で十分です。いくつかのスクリプトを準備するだけです。

最も低いRAM(mrxvt)を使用するアプリケーションも、実行中の他のアプリケーションを処理するために重要ですが、それを使用して目標を達成できない場合は役に立ちません。

答え1

「マルチターミナル」環境を探している場合は、ターミナル自体を見つけるのではなく(ターミネーターが良い選択です)、代わりにターミナルマルチプレクサへのパスを確認することをお勧めしますtmux

これにより、tmux高度な端末のすべての利点を享受できるだけでなく、すべての端末とリモートサーバーでも使用できます。

tmuxもう1つの利点は、ターミナルを閉じてもTMUXセッションがまだ存在して再開することができ、すべてのvimファイル、oプログラム、およびsshセッションがまだ実行中であることです。

事前定義されたTABS(tmuxのウィンドウ)を使用して複数の端末を構成し、いくつかのコマンドを自動的に実行するためにtmuxtmuxinator(https://github.com/tmuxinator/tmuxinator)とtmuxp(https://tmuxp.git-pull.com/)

tmuxpの例

session_name: 4-pane-split
start_directory: ./ # load session relative to config location (project root).
before_script: ./.tmuxp-before-script.sh
shell_command_before:
  - '[ -f .venv/bin/activate ] && source .venv/bin/activate && reset'
windows:
  - window_name: dev window
    layout: tiled
    shell_command_before:
      - cd ~/ # run as a first command in all panes
    panes:
      - shell_command: # pane no. 1
          - cd /var/log # run multiple commands in this pane
          - ls -al | grep \.log
      - echo second pane # pane no. 2
      - echo third pane # pane no. 3
      - echo forth pane # pane no. 4
  - window_name: docs
    layout: main-horizontal
    options:
      main-pane-height: 35
    start_directory: docs/
    panes:
      - focus: true
      - pane
      - make serve
      - make SPHINXBUILD='poetry run sphinx-build' watch

いくつかのリンク:

答え2

guake バージョン >= 3.8.5-1 の場合、以下が必要です。 (
cat >>bashAutoCmdOnStart.shそしてこのコマンドを ~/.bashrc の末尾に追加します。)

#!/bin/bash

strFlBase="/tmp/`basename "$0"`."

if [[ "$1" == "--getExecFileForUID" ]];then
  shift
  echo "Showing id for current term on guake:" >&2
  echo "${strFlBase}$1"
  exit 0
fi

#TODO for yakuake too
if [[ -z "$GUAKE_TAB_UUID" ]];then declare -p GUAKE_TAB_UUID;exit 0;fi

: ${bBashAutoCmdOnStart:=true} #help
if ! $bBashAutoCmdOnStart;then ps;pwd;declare -p bBashAutoCmdOnStart;exit 0;fi

ps;pwd
strFlExec="${strFlBase}$GUAKE_TAB_UUID"
nCount=0
while true;do
  echo -ne "$SECONDS: wating terminal auto cmd ($strFlExec). Hit any key for prompt.\r";
  #TODO test if terminal is interactive, I think `read` is failing when guake loads initially on pc restart
  if read -t 3 -n 1;then break;fi;
  if [[ -f "$strFlExec" ]];then
    echo "EXECUTING file contents '$strFlExec' here:"
    cat "$strFlExec"
    strRunFl="${strFlExec}.Running.${nCount}"
    mv -v "$strFlExec" "$strRunFl"
    #chmod +x "${strFlExec}.Running"
    source "${strRunFl}"
    ps;pwd
    #bash -c "${strFlExec}.Running;ps;pwd;bash"
    ((nCount++))&&:
  fi
done
ps;pwd
bBashAutoCmdOnStart=false bash

例を実行するには:guakeAutoEnv.sh [-x] -ID_CMD workA ls 123 -ID_CMD workB ls 456 789#-xは(現在のguakeタブではなく)xtermで実行します。 cat >>guakeAutoEnv.sh

#!/bin/bash

nWId="`wmctrl -l |grep "Guake!" |awk '{print $1}'`";declare -p nWId

: ${bUseBashAutoCmdMode:=false}
if ! qdbus org.guake3.RemoteControl /org/guake3/RemoteControl |grep execute_command_by_uuid;then
  #echoc --alert "@{-n}execute_command_by_uuid was @nremoved@{-n}, therefore this script wont work that way anymore :(";
  bUseBashAutoCmdMode=true
fi

if [[ -z "${1-}" ]] || [[ "${1}" == --help ]];then
  #help Usage ex.: [-x] -ID_CMD coolName ls 123 -ID_CMD funnyName ls 456 789
  egrep "[#]help" $0 |sed -r -e 's"^[[:space:]]*""' -e 's"[[:space:]]*$""' >/dev/stderr
  exit 0
fi

export bUsingXtermToRun=false;
if [[ "${1-}" == "-x" ]];then 
  bUsingXtermToRun=true;
  shift&&:;
  (xterm -e $0 "$@"&disown) #w/o -x now
  exit
fi

set -Eeu

# depends on
while ! pgrep -fa "`which guake`";do echo " >>>>> WARN:WaitingGuakeStart";sleep 3;done #this line checks for a running guake
while ! qdbus org.guake3.RemoteControl;do echo " >>>>> WARN:WaitingGuakeDBus";sleep 3;done #this line checks for a listening guake

function FUNCexecEcho() {
  echo " EXEC: $@" >/dev/stderr
  "$@"
};export -f FUNCexecEcho

function FUNCgrc() {
  FUNCexecEcho qdbus org.guake3.RemoteControl /org/guake3/RemoteControl org.guake3.RemoteControl."$@"
}

# read parameters
acmd=()
astrIdList=()
astrOptList=()
iIdIndex=0
function FUNCchkCmd() { if [[ "${1:0:7}" == "-ID_CMD" ]];then return 0;else return 1;fi; } # <"$1">
while ! ${1+false};do
  if FUNCchkCmd "${1}";then
    echo " >>> NEW ID_CMD iIdIndex=$iIdIndex:"
    astrOptList+=("${1#-ID_CMD}");shift
    astrIdList+=("$1");shift;
    continue;
  fi
  
  acmd+=("$1");shift
  if ${1+false} || FUNCchkCmd "${1}";then
    echo "astrOptList[$iIdIndex]='${astrOptList[$iIdIndex]}'"
    echo "astrIdList[$iIdIndex]='${astrIdList[$iIdIndex]}'"
    eval 'aIdCmd'${iIdIndex}'=("${acmd[@]}")';declare -p aIdCmd${iIdIndex}
    ((iIdIndex++))&&:
    acmd=()
  fi
done
declare -p astrIdList

# detect existing tabs
iTabCount="`FUNCgrc get_tab_count`"
iCurrentTabIndex="`FUNCgrc get_selected_tab`"
strCurrentTabUUID="`FUNCgrc get_selected_uuidtab`"
astrTabUUIDList=()
astrTabNameList=()
for((i=0;i<iTabCount;i++));do
  echo
  declare -p i
  strTabName="`FUNCgrc get_tab_name $i`";declare -p strTabName
  if((i==iCurrentTabIndex));then echo " CURRENT TAB";fi
  
  FUNCgrc select_tab $i
  astrTabUUIDList+=("`FUNCgrc get_selected_uuidtab`")
  astrTabNameList+=("`FUNCgrc get_tab_name $i`")
done
FUNCgrc select_tab $iCurrentTabIndex # this first is reached fast so the user has not to wait a long time
: ${bGoBackToInitialTab:=false} #help will re-select select the tab this script was run on at the end

declare -p astrTabUUIDList |tr '[' '\n'
declare -p astrTabNameList |tr '[' '\n'

function FUNCrunCmd() {
  strOpts="$1";shift
  strTabName="$1";shift
  strTabUUID="$1";shift
  iIdCmd="$1";shift

  aOptList=();if [[ -n "$strOpts" ]];then aOptList+=(`echo "$strOpts" |sed -r 's@(.)@\1 @g'`);fi
  
  echo
  echo " TabName: ${strTabName}, CMDOPTION(s): ${aOptList[@]} "
  
  eval 'acmdRun=("${aIdCmd'${iIdCmd}'[@]}")';declare -p acmdRun
  
  bSubShell=true
  bForceCurrentTab=false
  bRetryOnError=false
  for strOpt in "${aOptList[@]}";do
    case "$strOpt" in
      n)bSubShell=false;; #help CMDOPTION: The default is to run using `bash -c '$cmd'`. To disable this, use like ex.: `-ID_CMDn cd ComePathToApplyAtCurrentShell`
      c)bForceCurrentTab=true;if ! $bUsingXtermToRun;then echo " >>>>> WARNING <<<<< 'c' CMDOPTION is more reliable using '-x' option!!!";fi;; #help CMDOPTION: The tab name will only be ignored (but only if it does not exist ex.: "IgnoredCurrentTabName") and the current tab running this script will be used. This option is more reliable with -x option.
      r)bRetryOnError=true;; #help CMDOPTION: if the command fails returning any error, it will retry running it after 3s.
      *)$0 --help;echo "ERROR: invalid option '$strOpt' for strTabName='${strTabName}' and command: ${acmdRun[*]}";exit 1;;
    esac
  done
  
  # create and run a tmp script
  strFl="`tempfile`";chmod +x "$strFl"
  echo '#!/bin/bash
    cat $0; # review the command
    '"$(declare -p acmdRun)"'; # '"${acmdRun[@]}"'
    echo >'"${strFl}.started"'
    if '$bRetryOnError';then
      while ! "${acmdRun[@]}";do echo "failed error $?";sleep 3;done
    else
      "${acmdRun[@]}";
    fi
    ' >"$strFl"
    
  while true;do
    bForceIgnoreStart=false
    
    if $bUseBashAutoCmdMode && $bSubShell;then
      bSubShell=false
      echo "WARN: disabling subshell mode to let bUseBashAutoCmdMode work for now." >&2
    fi
    
    if $bSubShell;then
      strCmd="bash -c ${strFl}"
    else
      # can the command passed thru qdbus param cause some problem if it is too complex? `bash -c` above is to prevent that.
      strCmd="`declare -p acmdRun`;"'"${acmdRun[@]}"'
      bForceIgnoreStart=true
    fi
    
    if $bUseBashAutoCmdMode;then
      #echoc --alert "@{-n}execute_command_by_uuid was @nremoved@{-n}, therefore this script wont work that way anymore :(";
      #exit 1
      strExecFile="`bashAutoCmdOnStart.sh --getExecFileForUID "$strTabUUID"`"
      echo "$strCmd" >>"$strExecFile"
      while [[ -f "$strExecFile" ]];do
        #echo "INFO: Waiting '$strExecFile' be consumed..."
        read -p "(`date`)INFO: Waiting '$strExecFile' be consumed... skip waiting? (y/...)`echo -ne "\r"`" -t 1 -n 1 strResp&&:;if [[ "$strResp" == "y" ]];then break;fi
        sleep 1
      done
    else
      # this is for old guake version
      if [[ "$strTabUUID" == "USE_CURRENT_TAB" ]];then
        FUNCgrc execute_command "$strCmd"
      else
        FUNCgrc execute_command_by_uuid "$strTabUUID" "$strCmd"
      fi
    fi
    
    sleep 1 #wait it start running
    
    : ${bWaitStart:=true} #help wait the command start running before sending the next one
    bForceRetry=false
    bKeepTmpExecFile=false
    bReallyWaitStart=$bWaitStart;if $bForceIgnoreStart;then bReallyWaitStart=false;fi
    if $bReallyWaitStart;then
      if $bForceCurrentTab || [[ "$strCurrentTabUUID" == "$strTabUUID" ]];then
        echo " >>>>>>>>>>>> "
        echo " >>>>> ATTENTION!!! this command '${acmdRun[*]}' was requested to be run on this current tab [$iCurrentTabIndex]'${strTabName}'($strCurrentTabUUID), so this script will not wait for the command to start and the related temporary exec file '${strFl}' will be kept."
        echo " >>>>>>>>>>>> "
        bKeepTmpExecFile=true
      else
        nW=0
        while [[ ! -f "${strFl}.started" ]];do
          echo " >>>>>>>>>>>> "
          echo "     > `date`: Waiting ($((nW++))) the command start running:"
          echo "     > TAB: strTabName='${strTabName}',strTabUUID='$strTabUUID'"
          echo "     > CMD$iIdCmd: '${acmdRun[*]}'"
          echo "     > It may fail if there was some command typed and not executed yet there."
          echo "     > It may fail if there happened an input request there."
          echo "     > So you better check if no problem happened!"
          echo "     > But if no problem happened and you force a retry, it will be buffered and will execute again."
          echo "     > Force retry run now? (y/...)"
          echo " >>>>>>>>>>>> "
          strResp="$(read -t 3 -n 1 strResp;echo "$strResp")";echo #the script was stopping here... why did I have to subshell?
          if [[ "$strResp" == "y" ]];then echo " >>>>> Retrying";bForceRetry=true;break;fi
        done
      fi
    fi
    
    if ! $bForceRetry;then break;fi
  done
  
  : ${bRmTmpFiles:=false} #help delete temporary files
  if $bRmTmpFiles && ! $bKeepTmpExecFile;then rm -v "${strFl}" "${strFl}.started";fi
};export -f FUNCrunCmd

# run the commands
for iId in "${!astrIdList[@]}";do
  declare -p iId
  echo " Id: ${astrIdList[iId]}"
  
  bFound=false
  
  for iTab in "${!astrTabNameList[@]}";do
    strOpt="${astrOptList[iId]}"
    bRunOnThisTab=false
    if [[ "${astrTabNameList[iTab]}" == "${astrIdList[iId]}" ]];then bRunOnThisTab=true;fi
    if ((iTab==iCurrentTabIndex)) && [[ "$strOpt" =~ .*c.* ]];then bRunOnThisTab=true;fi
    if $bRunOnThisTab;then
      FUNCrunCmd "$strOpt" "${astrIdList[iId]}" "${astrTabUUIDList[iTab]}" $iId
      bFound=true
      break
    fi
  done
  
  : ${bAddTab:=true} #help if it doesnt exist yet
  if ! $bFound;then
    if $bAddTab;then
      FUNCgrc add_tab "$HOME"
      FUNCgrc rename_current_tab "${astrIdList[iId]}"
      astrTabNameList+=("${astrIdList[iId]}")
      astrTabUUIDList+=("`FUNCgrc get_selected_uuidtab`")
      FUNCrunCmd "${astrOptList[iId]}" "${astrIdList[iId]}" "USE_CURRENT_TAB" $iId
    else
      echo " >>>>>>>>>>>> "
      echo " >>>>> WARNING: could not find a matching tab name for '${astrIdList[iId]}'"
      echo " >>>>>>>>>>>> "
    fi
  fi
done #for iId in "${!astrIdList[@]}";do

if $bGoBackToInitialTab;then FUNCgrc select_tab $iCurrentTabIndex;fi

関連情報