2010-11-23 7 views
8

別のコマンドの出力を適切な場所にリダイレクトするbashスクリプトを作成しています。基本的には、スクリプトがシェル/コマンドラインから呼び出されたときに、出力をSTDOUTに送る必要があります。しかし、bashスクリプトが他のアプリケーション(例えば、別のbashスクリプト、アプリケーション、私の場合は素晴らしいウィンドウマネージャーの素晴らしいプロンプトから)から実行されたとき、出力を別の場所にリダイレクトしたいのです。bashスクリプトがシェルまたは別のスクリプト/アプリケーションから呼び出されたかどうか確認してください。

スクリプトがどのように呼び出されたかを見るための方法はありますか?

+1

それを見るもう1つの方法は、出力そのものをパイプするラッパースクリプトを使用するのはなぜですか?だから、素晴らしいウィンドウマネージャはscript-wrapper.shを呼び出し、これには "./script.sh >> awesome.log"という文字列が含まれています。 – laher

+1

シェルスクリプトのユーザーとして、私はスクリプトがあまりにも巧妙ではない。私はファイル内の出力をしたい場合、私は完全にそれを自分自身のファイルに置くことができます。ファイルに出力を送るためにラッパーやフラグをスクリプトに提供すると( '-o filename'など)、理想的です - 簡単ですが明示的です。 –

+0

良い点ですが、これを簡単にしたいと思います。問題のコマンドはTaskwarriorです。私は 'task add blah blah'と入力して、どこに入力しても心配しなくてもいいようにしたいだけです。毎回多くのリダイレクトやオプションを入力する必要がある場合は、十分ではないため使用しません。 –

答えて

16

はこれを試してみてください。その場合、あなたはまた、標準入力をチェックし、より汎用性の高い条件(ファイルディスクリプタ0)をお勧めしますそれはコマンドラインから実行されるか、またはスクリプト内でバックグラウンドで実行されていました。これらの2つに分けて伝える:

ps -o stat= -p $$ 

は、バックグラウンドでない場合は「+」を含みます。

(&)
Run   $$ $PPID 
CL   S+ Ss 
CL&   S  Ss+ 
Script  S+ S+ 
Script&  S  S 
Script(&) S  Ss 
Script&(&) S  NULL 

は、子スクリプトをバックグラウンドにされたことを意味し、&は、それがバックグラウンドにして走っている(「スクリプト」を指しものです)親スクリプトを意味します

は、ここでテーブルです。 CLはコマンドラインを意味します。 NULLはps出力がnullで、$PPIDが "1"であることを意味します。

man psから:

s is a session leader 
    + is in the foreground process group 

この答えはGNU psに基づいていることに留意すべきであるが、(OS Xを含む)BSDのmanページには、同様の機能を示しています。そしてGNU psは、とりわけBSD機能を含むハイブリッドです。

+2

テーブル内の「スクリプト」は、問題の対象となるスクリプトではなく、親スクリプトを意味します。 –

+0

非常に良い解決策。 –

-1

あなたが親のプロセス名の親変数を設定し、それを画面に印刷し

PARENT=`ps --no-heading -o %c -p $PPID` 
    echo $PARENT 

このような$ PPID

何かを使用することができます。

あなたはその後、いくつかを置くことができれば$親の値に基づいて文

HTH

+0

私はこれをテストし、直接実行するかどうかは関係ありません。* bash *スクリプトでは "bash"と表示されます。 – ndemou

+0

@ndemou Ubuntu 16.04、kernel 4.4.0-53の下で確認し、5年後に "bash" – WinEunuuchs2Unix

7

私は、あなたが本当に知りたいことはstdoutがターミナルであるかどうかであると信じています。そうであれば、それは対話的セッションであると(ほぼ)安全に仮定できます。次のコードを試してください。

if [[ -t 1 ]]; then 
     echo "Terminal" 
else 
     echo "Not-a-terminal" 
fi 

上記[[ -t 1 ]]コマンドは、ファイル記述子1(すなわち標準出力)が端末であるかどうかをチェックするものです。

EDIT:

あなたパイプならば、これは他のプログラムに出力非終端標準出力を示しますので、予めご了承ください。結果は「S」が含まれている場合(小文字)

ps -o stat= -p $PPID 

[[ -t 0 || -t 1 ]] 
+0

しかし、stdoutが端末にないとき(たとえパイプに入っているときなど)でも、コマンドラインから実行されているかどうかを知りたいかもしれません。 –

+0

@Dennis:これには普遍的または魔法の解決策はないと思います。 PPIDメソッドは有効ですが、スクリプトが別のスクリプトを通じて呼び出された場合にも失敗します。 – thkala

+0

あなたは3番目のレベルについて話していますか?スクリプトを呼び出すスクリプトを呼び出すスクリプトですか?私の答えにこのテクニックを使用して、関心のあるスクリプトがコマンドラインから実行されたかどうかを判断することができます。 –

1

これは、このトピックに関する別の記事から取り上げた機能です。これは、上限までのすべての親プロセスと、$shells変数にリストされている項目とを照合します。実行されると、$iscliは0または1のいずれかに設定されます。0に設定されている場合、シェルから実行されたこと、またはこの目的のために十分なシェルとみなされます。 1に設定されている場合、承認されていないプログラムが含まれていることがわかります。私はシェルとPHPで実行したいスクリプトに対して、それぞれに異なる出力を提供したいときにこれを使います。

$iscliに値が必要になる前に、パラメータを指定せずに最初にこの関数を呼び出す必要があります。

function top_level_parent_pid { 

    scriptname="${0##*/}" 
    shells="^bash|^init|^screen|^sh|^ssh|^su|${scriptname}" 

    pid=${1:-$$} 
    pidname="`ps --no-heading -o %c -p ${pid}`" 
    stat=($(</proc/${pid}/stat)) 
    ppid=${stat[3]} 
    ppidname="`ps --no-heading -o %c -p ${ppid}`" 
    isclitest="`echo "${ppidname}" | grep -iv -E "${shells}"`" 

    until [ "${ppid}" -eq "1" ] || [ "${iscli}" = "1" ]; do 

      if [[ -n "${isclitest}" ]]; then 

        iscli="1" 

       else 

        iscli="0" 


        top_level_parent_pid ${ppid} 
      fi 
    done 
} 
関連する問題