Saya mencoba menggunakan skrip ekspektasi untuk mengakses perangkat jarak jauh melalui telnet, membaca/menyimpan "EVENTLOG" jarak jauh secara lokal, dan kemudian mengekstrak baris tertentu (nomor seri) dari file log. Masalahnya adalah file log terus berubah jadi saya perlu cara untuk mencari string tertentu. Perangkat jarak jauh berbasis Linux, tetapi tidak memiliki hal-hal seperti grep, vi, less, dll karena QNX Neutrino, karenanya harus melakukannya secara lokal.

Saya telah berhasil mendapatkan telnet, membaca file dan menyimpan secara lokal di bawah kendali, tetapi ketika saya "membaca" file tersebut adalah ketika saya memiliki masalah. Saat ini saya hanya mencoba untuk mencetak apa yang ditemukannya, tetapi skrip keluar begitu saja tanpa melaporkan apa pun kecuali beberapa kawat gigi tambahan ??

#!/usr/bin/expect -f

set timeout -1
    log_user 1

    spawn telnet $IP
    match_max 100000
    expect "login:"
    send -- "$USER\r"
    expect "Password:"
    send -- "$PW\r"
    expect "# "
    send -- "\r"

#at this point logged into device
#send command to generate the "dallaslog"

    set dallaslog [open dallaslog.txt w]
    expect "#" 
        send -- "cat `ls -rt /LOG/event*`\r"

    expect "(cat) exited status=0"
    set logout $expect_out(buffer)
    puts $dallaslog "$logout"
    close $dallaslog
    unset expect_out(buffer)

    set dallasread [open dallaslog.txt r]
    set lines [split [read $dallasread] "\r"]
    close $dallasread

    puts "${green}$lines{$normal}"
#a debug line to print $dallasread in green so I can verify it works up to here

    foreach line $lines {
        if {[regexp {.*Dallas ID: 0.*\n} $lines match]} {
        if {$match == 1} {
            puts $line  ;# Prints whole line which has 1 at end 
        }
        }
    }
    expect "# "
    send -- "exit\r"
    interact

Apa yang saya (akhirnya) cari adalah skrip untuk menangkap baris apa pun yang dimulai dengan "Dallas ID:" dan kemudian menyimpan informasi itu ke variabel, jadi saya bisa menggunakan perintah "scan" untuk mengurai baris dan mengekstrak informasi.

Yang saya dapatkan adalah:

(the results from $lines being "puts" in green)
"...
<ENTRY TIME="01/01/1970 00:48:07" PROC="syncd" FILE="mips.cc" LINE="208" NUM="10000">
UTC step from 01/01/1970 00:48:08 to 01/01/1970 00:48:07
</ENTRY>

Process 3174431 (cat) exited status=0
}{}
# exit

Process 3162142 (sh) exited status=0.
Connection closed by foreign host."

Terima kasih sebelumnya atas semua bantuannya. Saya seorang pemula untuk TCL/harapan (telah mempermainkannya sejak Juli lalu) tetapi saya menemukan itu sebagai alat yang cukup kuat, hanya sulit bagi saya untuk men-debug!

EDIT: Menambahkan lebih banyak informasi per tanggapan @meuh. Contoh: Dapat ada hingga 4 Dallas ID, tetapi umumnya saya hanya memiliki 0 dan 1. Tujuannya adalah untuk mendapatkan SN, BC, CN untuk mencapai Dallas ID disimpan sebagai variabel untuk dimasukkan ke dalam file teks terpisah.

<ENTRY TIME="01/01/1970 00:00:06" PROC="sys" FILE="PlatformUtils.cpp" LINE="1227" NUM="10044">
Dallas ID: 1 SN:00000622393A BC: J4AD945 CN: IS200BPPBH2BMD R0: 001C 
</ENTRY>

Loop foreach yang saya gunakan adalah contoh dari pertanyaan lama tentang stack overflow yang saya coba modifikasi untuk digunakan di sini, tidak berhasil.

EDIT: Saya mungkin juga harus menyebutkan bahwa log peristiwa ini panjangnya kira-kira 800 baris setiap kali dibaca, itulah sebabnya saya belum memposting kutipan darinya.

2
JohnnyD 13 Agustus 2019, 02:11

1 menjawab

Jawaban Terbaik

Baris regexp ini mungkin tidak melakukan apa yang Anda inginkan:

if {[regexp {.*Dallas ID: 0.*\n} $lines match]} {
    if {$match == 1} {
        puts $line  

Anda melewati daftar $lines alih-alih, mungkin, satu baris $line. Variabel match akan disetel ke string yang cocok yang karenanya harus menyertakan kata "Dallas" dan seterusnya, jadi tidak akan pernah menjadi 1. Komentar kode Anda mengatakan Mencetak seluruh baris yang memiliki 1 di akhir, tetapi saya tidak yakin apa yang Anda cari karena Anda tidak memiliki contoh data yang sesuai dengan regexp.

Jika Anda memilih pola regexp Anda menggunakan pengelompokan, Anda dapat menangkap bagian dari garis sehingga mungkin tidak memerlukan scan lebih lanjut. Misalnya

regexp {PROC="([a-z]*)"} $line match submatch

Akan mengatur submatch variabel ke syncd dalam contoh Anda di atas.


Anda mungkin juga memiliki masalah mendasar yang disebabkan oleh penanganan \r\n tcl pada input dari file. Baris yang Anda dapatkan dari $expect_out(buffer) memang memiliki 2 karakter sebagai pembatas akhir baris. Namun, saat menggunakan read, secara default saya percaya, itu akan menerjemahkan urutan yang sama ke \n yang dinormalisasi. Jadi pemisahan Anda tidak akan menghasilkan apa-apa, dan Anda perlu membagi pada \n daripada \r. Anda dapat memeriksa ukuran daftar garis yang Anda miliki

puts [llength $lines]

Jika 1, maka split Anda tidak berfungsi. Ganti dengan

set lines [split [read $dallasread] "\n"]

Ini akan membantu loop Anda, di mana misalnya Anda dapat mencoba

foreach line $lines {
    if {[regexp {.*Dallas ID: (\d+) SN:([^ ]+)} $line match idnum SN]} {
        puts $line
        puts "$idnum, $SN"
    }
}    

Anda harus menghapus \n di akhir regexp Anda, karena ini tidak lagi ada setelah pemisahan. Saya telah memperluas contoh regexp dengan (\d+) agar sesuai dengan nomor id (\d cocok dengan digit), dan ([^ ]+) untuk mencocokkan sejumlah karakter non-spasi setelah teks SN:.

Nilai-nilai ini ditangkap dengan menggunakan pengelompokan (), dan ditempatkan di variabel idnum dan SN, yang seharusnya dapat Anda lihat outputnya dengan perintah puts kedua.

0
meuh 13 Agustus 2019, 18:46