ssh、suを使用してセッションを維持し、自分のセッション環境にのみ影響を与えるにはどうすればよいですか?

ssh、suを使用してセッションを維持し、自分のセッション環境にのみ影響を与えるにはどうすればよいですか?

suリモートサーバー(Amazon Linux 2)にSSHを介して同時にいくつかのコマンドを実行し、次の単一スクリプトでSSHセッションを維持したいと思います。

ssh -t ec2-user@$host -i $keypath \
  'sudo -iu some-user bash -c "
   echo a; 
   c(){ clear; };
   echo b; 
   "'

出力:

a
b
Connection to xx.xx.xx.xx closed.

だから少しずつ改善するにつれて

ssh -t ec2-user@$host -i $keypath \
  'sudo -iu some-user bash -c "
   echo a; 
   c(){ clear; };
   echo b; 
   bash -l;
   echo c; 
   "'

出力:

a
b  

(その後、SSH経由でsome-userユーザーとしてリモートにログインし、セッションを維持することに成功しました。)

しかし、

# on the remote
$ whoami
some-user
$ c  
bash: c: command not found  

cSSH経由のユーザー:some-userとしてログインした後、コマンドが機能したいと思います。
この問題をどのように解決できますか?

注:
1.
bash -lSSHセッションをアクティブにしてください。削除するとSSHにログアウトします。
2.
他の人のSSHセッションではなく、私のSSHセッションにのみ影響を与えたいので、~/.bashrcのような初期化ファイルを編集したくありません。
3. SSH ログイン後
はできますalias c=clear。しかし、10個の(機能的)エイリアスを設定し、10個の異なるリモコンがあると面倒です。
4.
リモートシェルは /bin/bash です。

答え1

あなたの例では、エイリアシングが機能しているか機能していないことを示していません。実際に動作するかもしれませんが、不明であり、とにかくそこには役に立ちません。

Aliasは、現在のシェルのシェルエイリアスを設定するために使用されるシェル組み込みコマンドです。シェルのメモリを除くどこにもエイリアスを保存しません。

新しいシェルを起動すると、他のシェルインスタンスのエイリアスは覚えていません。シェル全体でエイリアスを記憶するには、そのエイリアスがシェル初期化ファイルの1つになければなりません。

仮に、このようなコマンドは非対話型で実行され、多くのシェル初期化ファイルは非対話型シェルのエイリアスをロードするように構成されていません。また、シェルがロードする初期化ファイルは、これがログインシェルかサブシェルか、一時非反復シェルかによって異なります。さらに、シェルオプションはinitファイルのロードを明示的に無効にすることができます。したがって、非対話型シェルでエイリアスを使用できるようにするには、エイリアスを生成するシェル初期化ファイルに注意する必要があります。

この組み合わせにsudoを追加すると、状況がさらに混乱します。ルートシェルでこのエイリアスを使用しますか?その後、ルートのシェル初期化ファイルに配置する必要があります。

bashのLinuxベースシェルが対話型シェルであると仮定すると、~/.bashrcエイリアスを使用したいすべてのユーザー(ルートを含む)はエイリアスを使用できます。

答え2

エイリアスはトリッキーです。関連部分は次のとおりですman bash(強調)。

エイリアスの定義と使用に関する規則は多少混乱しています。 Bash は、その行または複合コマンドからコマンドを実行する前に、入力の完全な 1 行と複合コマンドを構成するすべての行を常に読み込みます。エイリアスは、コマンドの実行時ではなく、コマンドの読み込み時に拡張されます。 したがって、他のコマンドと同じ行に表示されるエイリアス定義は、次の入力行を読むまで適用されません。。行のエイリアス定義の後に続くコマンドは、新しいエイリアスの影響を受けません。この動作は関数の実行時にも問題になります。エイリアスは、関数定義自体がコマンドであるため、関数が実行されるのではなく、関数定義を読み取るときに拡張されます。その結果、
関数内で定義されたエイリアスは、関数の実行後にのみ使用できます。 安全のために、常に別名定義を別々の行に配置し、複合コマンドに別名を使用しないでください。

ほとんどすべての目的で、エイリアスはシェル関数に置き換えられます。

つまり、このように非対話型シェルでエイリアスを使用するには、次のようにエイリアスを明示的に有効にする必要があります。shopt -s expand_aliases そして別名定義を別の行に入力する必要があります。 Aは;それを切らないでしょう。実際の改行が必要です。

## fails
$ ssh localhost 'alias ff="echo \"I am an alias!\""; ff'
bash: line 1: ff: command not found

## fails
$ ssh localhost 'alias ff="echo \"I am an alias!\""; shopt -s expand_aliases; ff'
bash: line 1: ff: command not found

## works
$ ssh localhost 'alias ff="echo \"I am an alias!\""; shopt -s expand_aliases; 
> ff'
I am an alias!

これは…あなたが望むものではないようです。まず、正直なところ、あなたがしなければならないことは、この非常に複雑な方法を扱うのではなく、これらすべてのコマンドをスクリプトに入れてそのスクリプトを実行するようです。この作業に固執する場合は、少なくともエイリアスの代わりに関数を使用してください。

$ ssh localhost 'ff(){ echo "I am a function!";}; ff'
I am a function!

これがどれくらい簡単か見てみませんか?

今、あなたが説明するエラーや動作は、あなたが提供したコマンドと一致しません。ただし、表示されたコマンドを実行するには、関数を使用して次の操作を実行できます。

ssh -t ec2-user@$host -i $keypath \
  'sudo -iu some-user bash -c "mkdir -p /tmp/test/; cd /tmp/test ; 
   echo THIS_IS_TEST; 
   c(){ clear; }
   touch test-txt; 
   c"'

この場合、話すことはできないので、まだ話し合いません。何もできないという意味なのでclear削除しました。bash -l私はあなたがおそらく新しい質問をし、ここで最終目標が何であるかを説明しなければならないと思います。どのような作業を行っても、これが最善のアプローチではない可能性があるため、新しい質問をしたり詳細を提供したりすると、より良いアプローチを提供できるはずです。

答え3

ジョブ制御を有効にする必要があると思います。

#! /bin/bash

set -m

基本的に有効にする必要がありますが、なぜそうなのかわかりません。

関連情報