dapatkah Anda menjelaskan apa yang Anda maksud dengan "baris perintah"?
Bart
Saya hanya ingin tahu apakah ada variabel dolar khusus yang berisi string lengkap (baris perintah), bukan hanya nama skrip dan argumennya
hellcode
2
Apa yang akan Anda gunakan untuk melakukan hal ini?
Kusalananda
9
@ kode sandi Anda tidak perlu tahu apakah Anda berada di dalam pipa untuk itu. Periksa apakah output adalah TTY. [ -t 1 ]unix.stackexchange.com/a/401938/70524
Tetapi bashshell interaktif dapat memanfaatkan mekanisme histori dan DEBUGjebakan untuk "memberi tahu" perintah yang menjalankan baris perintah lengkap yang menjadi bagian mereka melalui variabel lingkungan:
Meskipun bermanfaat, ini hanya berfungsi di Linux - bukan Unix lain
Scott Earle
2
Dengan menggunakan /proc/self/fd, Anda dapat melihat apakah Anda berada di jalur pipa serta ID untuk pipa tersebut. Jika Anda beralih melalui /proc/\*/fdmencari pipa yang cocok, Anda dapat menemukan PID dari ujung pipa yang lain. Dengan PID, Anda dapat membaca /proc/$PID/cmdlineserta mengulangi proses pada deskriptor file untuk menemukan apa yang disalurkan.
$ cat | cat | cat &
$ ps
PID TTY TIME CMD6942 pts/1600:00:00 cat6943 pts/1600:00:00 cat6944 pts/1600:00:00 cat7201 pts/1600:00:00 ps20925 pts/1600:00:00 bash
$ ls -l /proc/6942/fd
lrwx------.1 tim tim 64Jul2419:590->/dev/pts/16
l-wx------.1 tim tim 64Jul2419:591->'pipe:[49581130]'
lrwx------.1 tim tim 64Jul2419:592->/dev/pts/16
$ ls -l /proc/6943/fd
lr-x------.1 tim tim 64Jul2419:590->'pipe:[49581130]'
l-wx------.1 tim tim 64Jul2419:591->'pipe:[49581132]'
lrwx------.1 tim tim 64Jul2419:592->/dev/pts/16
$ ls -l /proc/6944/fd
lr-x------.1 tim tim 64Jul2419:590->'pipe:[49581132]'
lrwx------.1 tim tim 64Jul2419:591->/dev/pts/16
lrwx------.1 tim tim 64Jul2419:592->/dev/pts/16
Juga jika Anda beruntung, perintah yang berbeda dalam pipa akan mendapatkan PID berurutan yang akan membuatnya sedikit lebih mudah.
Saya sebenarnya tidak memiliki skrip untuk melakukan ini, tetapi saya telah membuktikan konsepnya.
Di sini $BASH_COMMANDdiperluas sementara juga membersihkannya hingga evalsedikit string, dan string hasil dengan demikian "snapshotted" menjadi $CMDvariabel pembantu .
Terima kasih atas jawaban anda Saya telah menguji berbagai hal dan membuka skrip pengujian berikut:
test.sh:
hist=`fc -nl -0`# remove leading and trailing whitespaces
hist="$(echo "${hist}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
echo "Command line from history: '$hist'"if[-t 1];then
echo "Direct output to TTY, no pipe involved."else
echo "No TTY, maybe a piped command."fiif[-p /dev/stdout ];then
echo "stdout is a pipe."else
echo "stdout is not a pipe."fi
readlink -e /proc/self/fd/1
rst=$?if[ $rst -eq 0];then
echo "Readlink test status okay, no pipe involved."else
echo "Readlink test status error $rst, maybe a piped command."fi
Tes:
$ ./test.sh test1Command line from history:'./test.sh test1'Direct output to TTY, no pipe involved.
stdout is not a pipe./dev/pts/3Readlink test status okay, no pipe involved.
$ ./test.sh test2 | catCommand line from history:'./test.sh test2 | cat'No TTY, maybe a piped command.
stdout is a pipe.Readlink test status error 1, maybe a piped command.
$ echo "another command before pipe doesn't matter"|./test.sh test3Command line from history:'echo "another command before pipe doesn't matter" | ./test.sh test3'
Direct output to TTY, no pipe involved.
stdout is not a pipe.
/dev/pts/3
Readlink test status okay, no pipe involved.
Riwayat baris perintah hanya berfungsi tanpa Shebang di baris teratas skrip. Tidak tahu apakah ini akan bekerja andal dan pada sistem lain juga.
Saya tidak dapat menekan output dari "readlink" (atau "file" seperti yang disarankan dari Archemar), ketika statusnya berhasil ("/ dev / pts / 3"). Output perpipaan ke / dev / null atau ke suatu variabel akan menyebabkan kegagalan fungsi. Jadi ini bukan pilihan bagi saya dalam naskah.
Pemeriksaan TTY bahwa muru disebutkan mudah dan mungkin sudah cukup untuk beberapa kasus penggunaan.
Sunting: Kredit saya jatuh ke mosvy, karena pertanyaannya adalah bagaimana cara mendapatkan baris perintah yang lengkap dan bukan hanya untuk menentukan apakah skrip ada di pipa. Saya suka bagian sederhana "fc -nl -0" dalam jawabannya, karena tidak ada konfigurasi sistem lebih lanjut yang diperlukan. Ini bukan solusi 100 persen, tetapi ini hanya untuk penggunaan pribadi saya dan karena itu cukup. Terima kasih untuk semua yang lain atas bantuan Anda.
Cek TTY juga dapat dilakukan untuk stdin: [ -t 0 ]. Jadi Anda dapat memeriksa apakah stdin atau stdout bukan TTY dan lanjutkan.
muru
Jika Anda ingin tahu apakah stdout adalah sebuah pipa, di Linux Anda dapat menggunakan if [ -p /dev/stdout ]; ...(seperti readlink /proc/self/fd/..ini tidak berfungsi pada BSD).
Mosvy
2
Script perlu bekerja IMNSHO. yang echo -ehampir pasti tidak ingin -e. Anda perlu lebih banyak kasus uji, mengarahkan ke file, dipanggil di dalam $(...). Namun saya ingin Anda mempertimbangkan apakah ini ide yang bagus. Program seperti lsyang mengubah output mereka tergantung pada apakah mereka mengeluarkan ke tty atau pipa yang mengganggu untuk digunakan.
[ -t 1 ]
unix.stackexchange.com/a/401938/70524Jawaban:
Tidak ada cara untuk melakukan itu secara umum .
Tetapi
bash
shell interaktif dapat memanfaatkan mekanisme histori danDEBUG
jebakan untuk "memberi tahu" perintah yang menjalankan baris perintah lengkap yang menjadi bagian mereka melalui variabel lingkungan:sumber
tidak
bash (atau shell Anda) akan melakukan dua perintah berbeda.
test.sh arg1
grep "xyz"
test.sh
tidak bisa tahu tentang mengikuti grep.Namun Anda mungkin tahu Anda "di dalam" pipa dengan pengujian
/proc/self/fd/1
test.sh
yang dijalankan sebagai
(Sunting) lihat komentar muru tentang mengetahui apakah Anda menggunakan pipa.
sumber
Dengan menggunakan
/proc/self/fd
, Anda dapat melihat apakah Anda berada di jalur pipa serta ID untuk pipa tersebut. Jika Anda beralih melalui/proc/\*/fd
mencari pipa yang cocok, Anda dapat menemukan PID dari ujung pipa yang lain. Dengan PID, Anda dapat membaca/proc/$PID/cmdline
serta mengulangi proses pada deskriptor file untuk menemukan apa yang disalurkan.Juga jika Anda beruntung, perintah yang berbeda dalam pipa akan mendapatkan PID berurutan yang akan membuatnya sedikit lebih mudah.
Saya sebenarnya tidak memiliki skrip untuk melakukan ini, tetapi saya telah membuktikan konsepnya.
sumber
Cara lain mungkin dengan mengakses
$BASH_COMMAND
variabel otomatis, tetapi secara inheren volatile dan sulit untuk menangkap nilai yang diinginkan.Saya pikir Anda hanya bisa menangkapnya hanya melalui
eval
, yang juga melibatkan pemanggilan perintah Anda dengan cara khusus, seperti di:Di sini
$BASH_COMMAND
diperluas sementara juga membersihkannya hinggaeval
sedikit string, dan string hasil dengan demikian "snapshotted" menjadi$CMD
variabel pembantu .Sedikit contoh:
Secara alami itu juga bisa bekerja (sebenarnya lebih baik) sambil memohon skrip dengan misalnya
sh -c
ataubash -c
, seperti pada:Di sini tanpa membersihkan variabel.
sumber
Terima kasih atas jawaban anda Saya telah menguji berbagai hal dan membuka skrip pengujian berikut:
test.sh:
Tes:
Riwayat baris perintah hanya berfungsi tanpa Shebang di baris teratas skrip. Tidak tahu apakah ini akan bekerja andal dan pada sistem lain juga.
Saya tidak dapat menekan output dari "readlink" (atau "file" seperti yang disarankan dari Archemar), ketika statusnya berhasil ("/ dev / pts / 3"). Output perpipaan ke / dev / null atau ke suatu variabel akan menyebabkan kegagalan fungsi. Jadi ini bukan pilihan bagi saya dalam naskah.
Pemeriksaan TTY bahwa muru disebutkan mudah dan mungkin sudah cukup untuk beberapa kasus penggunaan.
Sunting: Kredit saya jatuh ke mosvy, karena pertanyaannya adalah bagaimana cara mendapatkan baris perintah yang lengkap dan bukan hanya untuk menentukan apakah skrip ada di pipa. Saya suka bagian sederhana "fc -nl -0" dalam jawabannya, karena tidak ada konfigurasi sistem lebih lanjut yang diperlukan. Ini bukan solusi 100 persen, tetapi ini hanya untuk penggunaan pribadi saya dan karena itu cukup. Terima kasih untuk semua yang lain atas bantuan Anda.
sumber
[ -t 0 ]
. Jadi Anda dapat memeriksa apakah stdin atau stdout bukan TTY dan lanjutkan.if [ -p /dev/stdout ]; ...
(sepertireadlink /proc/self/fd/..
ini tidak berfungsi pada BSD).echo -e
hampir pasti tidak ingin-e
. Anda perlu lebih banyak kasus uji, mengarahkan ke file, dipanggil di dalam$(...)
. Namun saya ingin Anda mempertimbangkan apakah ini ide yang bagus. Program sepertils
yang mengubah output mereka tergantung pada apakah mereka mengeluarkan ke tty atau pipa yang mengganggu untuk digunakan.