1

Тема: CMD/BAT: Аналог bash на bat

в скрипте есть функция grep Raw_Read_Error_Rate | awk '{print $4}'  которая берет из файла строки которые начинаются с Raw_Read_Error_Rate и выводит 4 столбец в этой строке.  Можно ли на bat сделать такое же?

2

Re: CMD/BAT: Аналог bash на bat

Что такое «четвёртый столбец»? А так — да:

@echo off
setlocal enableextensions enabledelayedexpansion

set sSourceFile=0001.txt

for /f "usebackq tokens=4" %%i in (
    `type "%sSourceFile%" ^| findstr.exe /r /b /c:"Raw_Read_Error_Rate"`
) do echo.%%i

endlocal
exit /b 0

3

Re: CMD/BAT: Аналог bash на bat

4 столбец - VALUE.



Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME           FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  1  Raw_Read_Error_Rate     0x000f   120   099   006    Pre-fail  Always       -       236997101
  3  Spin_Up_Time            0x0003   100   100   000    Pre-fail  Always       -       0
  4  Start_Stop_Count        0x0032   099   099   020    Old_age   Always       -       1152
  5  Reallocated_Sector_Ct   0x0033   100   100   036    Pre-fail  Always       -       0
  7 Seek_Error_Rate          0x000f   084   060   030    Pre-fail  Always       -       244136058

4

Re: CMD/BAT: Аналог bash на bat

Вопрос более конкретный
На баше сделано так: берется файл с отчетом, см. выше пример.
Значениям ValueSmart1 и ThresholdSmart1 присваиваются соответствующие значения из отчета, данные берутся по столбцам.

ValueSmart1=$(cat /tmp/smartsda.txt | grep Raw_Read_Error_Rate | awk '{print $4}')
ThresholdSmart1=$(cat /tmp/smartsda.txt | grep Raw_Read_Error_Rate | awk '{print $6}')

if [ $ValueSmart1 -le $ThresholdSmart1 ]
then

берутся 4 и 6 столбцы и сравниваются между собой. Можно ли что-то подобное на батнике сделать?

5

Re: CMD/BAT: Аналог bash на bat

Что-либо «подобное» — можно. Только где ж тут «строки которые начинаются с Raw_Read_Error_Rate», а?

@echo off
setlocal enableextensions enabledelayedexpansion

set sSourceFile=C:\Песочница\057\0001.txt

if exist "%sSourceFile%" (
    for /f "usebackq tokens=4,6" %%i in (
        `type "%sSourceFile%" ^| find.exe /i "Raw_Read_Error_Rate"`
    ) do (
        set sValueSmart=%%i
        set sThresholdSmart=%%j
    )

    if defined sValueSmart (
        if defined sThresholdSmart (
            if !sValueSmart! leq !sThresholdSmart! (
                echo ValueSmart [!sValueSmart!] less or equal than ThresholdSmart [!sThresholdSmart!]
            ) else (
                echo ValueSmart [!sValueSmart!] greater than ThresholdSmart [!sThresholdSmart!]
            )
        ) else (
            echo Can't find [ThresholdSmart] value.
            exit /b 3
        )
    ) else (
        echo Can't find [ValueSmart] value.
        exit /b 2
    )
) else (
    echo Can't find source file [%sSourceFile%].
    exit /b 1
)

endlocal
exit /b 0

P.S. C bash не знаком.

6

Re: CMD/BAT: Аналог bash на bat

Благодарю, все работает, подправил под себя для отправки писем.
И последний вопрос, если можно: можно ли здесь же сделать сравнение не по одной строке, а по нескольким: т.е. брать например  еще

5  Reallocated_Sector_Ct 
7 Seek_Error_Rate
и в них так же сравнивать те же столбцы?

7

Re: CMD/BAT: Аналог bash на bat

Можно продублировать весь участок, начиная с «for /f "usebackq tokens=4,6" %%i in (…», заменив «Raw_Read_Error_Rate» на потребное. Если не то — опишите желаемое подробнее.

8

Re: CMD/BAT: Аналог bash на bat

Если продублировать - получится не совсем то: он будет выполняться последовательно, по этому будет несколько писем.

@echo off
setlocal enableextensions enabledelayedexpansion

set sSourceFile=C:\smarta.txt

if exist "%sSourceFile%" (
    for /f "usebackq tokens=4,6" %%i in (
        `type "%sSourceFile%" ^| find.exe /i "Raw_Read_Error_Rate"`
    ) do (
        set sValueSmart=%%i
        set sThresholdSmart=%%j
    )

    if defined sValueSmart (
        if defined sThresholdSmart (
            if !sValueSmart! leq !sThresholdSmart! (
                echo ValueSmart [!sValueSmart!] less or equal than ThresholdSmart [!sThresholdSmart!]
                C:\sendemail.exe -f messages@mail -t admin@mail -u PROBLEM: SMART %COMPUTERNAME%
            ) else (
                echo ValueSmart [!sValueSmart!] greater than ThresholdSmart [!sThresholdSmart!]
                C:\sendemail.exe -f messages@mail -t admin@mail -u OK: SMART %COMPUTERNAME% 

            )
        ) else (
            echo Can't find [ThresholdSmart] value.
            exit /b 3
        )
    ) else (
        echo Can't find [ValueSmart] value.
        exit /b 2
    )
) else (
    echo Can't find source file [%sSourceFile%].
    exit /b 1
)

endlocal
exit /b 0

получится что если дублировать цикл проверки, то при каждом проходе будет отправляться сообщение.
Если я правильно понимаю.

А хотелось бы так: сравниваются значения из нужных строк и если какое либо условие не проходит - отправляется письмо.


Для понятия приведу пример



ValueSmart2=$(cat /tmp/smartsda.txt | grep Spin_Up_Time | awk '{print $4}')
ThresholdSmart2=$(cat /tmp/smartsda.txt | grep Spin_Up_Time | awk '{print $6}')
Opisanie2="Если VALUE стало меньше THRESH в случае Pre-fail атрибута — существует большая вероятность, что диск вылетит в ближайшие 24 часа. Spin Up Time - время раскрутки пакета дисков из состояния покоя до рабочей скорости. При расчете нормализованного значения (Value) практическое время сравнивается с некоторой эталонной величиной, установленной на заводе. Не ухудшающееся немаксимальное значение при Spin Up Retry Count Value = max (Raw равном 0) не говорит ни о чем плохом. Отличие времени от эталонного может быть вызвано рядом причин, например просадка по вольтажу блока питания."


ValueSmart3=$(cat /tmp/smartsda.txt | grep Reallocated_Sector_Ct | awk '{print $4}')
ThresholdSmart3=$(cat /tmp/smartsda.txt | grep Reallocated_Sector_Ct | awk '{print $6}')
Opisanie3="Если VALUE стало меньше THRESH в случае Pre-fail атрибута — существует большая вероятность, что диск вылетит в ближайшие 24 часа. Reallocated Sector Count - число операций переназначения секторов. SMART в современных дисках способен произвести анализ сектора на стабильность работы на лету и в случае признания его сбойным, произвести его переназначение."

ValueSmart5=$(cat /tmp/smartsda.txt | grep Spin_Retry_Count | awk '{print $4}')
ThresholdSmart5=$(cat /tmp/smartsda.txt | grep Spin_Retry_Count | awk '{print $6}')
Opisanie5="Если VALUE стало меньше THRESH в случае Pre-fail атрибута — существует большая вероятность, что диск вылетит в ближайшие 24 часа. Spin Up Retry Count - число повторных попыток раскрутки дисков до рабочей скорости, в случае если первая попытка была неудачной. Ненулевое значение Raw (соответственно немаксимальное Value) свидетельствует о проблемах в механической части накопителя."


if [ $ValueSmart1 -le $ThresholdSmart1 ]
then
    cat /tmp/smartsda.txt | /usr/local/bin/email -f info@mail.in -n SMART -b -no-encoding $EMAIL -s "PROBLEM: SMART  Raw_Read_Error_Rate, Value="$ValueSmart1", Threshold="$ThresholdSmart1 
elif [ $ValueSmart2 -le $ThresholdSmart2 ]
then
    cat /tmp/smartsda.txt | /usr/local/bin/email -f info@mail.in -n SMART -b -no-encoding $EMAIL -s "PROBLEM: SMART  Spin_Up_Time, Value="$ValueSmart2", Threshold="$ThresholdSmart2
elif [ $ValueSmart3 -le $ThresholdSmart3 ]
then
    cat /tmp/smartsda.txt | /usr/local/bin/email -f info@mail.in -n SMART -b -no-encoding $EMAIL -s "PROBLEM: SMART  Spin_Retry_Count, Value="$ValueSmart5", Threshold="$ThresholdSmart5
else
    cat /tmp/smartsda.txt | /usr/local/bin/email -f info@mail.in -n SMART -b -no-encoding $EMAIL -s "OK: SMART 
fi

9

Re: CMD/BAT: Аналог bash на bat

и если какое либо условие не проходит - отправляется письмо.

Ну, вот, как-то так (не проверялось):

@echo off
setlocal enableextensions enabledelayedexpansion

set sSourceFile=C:\Песочница\057\0001.txt
set sStrings=Raw_Read_Error_Rate Reallocated_Sector_Ct Seek_Error_Rate

if exist "%sSourceFile%" (
    for %%i in (%sStrings%) do for /f "usebackq tokens=4,6" %%j in (
        `type "%sSourceFile%" ^| find.exe /i "%%~i"`
    ) do (
        set sValueSmart=%%j
        set sThresholdSmart=%%k
        
        if defined sValueSmart (
            if defined sThresholdSmart (
                if !sValueSmart! leq !sThresholdSmart! (
                    echo ValueSmart [!sValueSmart!] less or equal than ThresholdSmart [!sThresholdSmart!]
                    set /a bProblemFound = 1
                ) else (
                    echo ValueSmart [!sValueSmart!] greater than ThresholdSmart [!sThresholdSmart!]
                )
            ) else (
                echo Can't find [ThresholdSmart] value for [%%~i] parameter.
                exit /b 3
            )
        ) else (
            echo Can't find [ValueSmart] value for [%%~i] parameter.
            exit /b 2
        )
    )
    
    if defined bProblemFound (
        "C:\sendemail.exe" -f messages@mail -t admin@mail -u PROBLEM: SMART %COMPUTERNAME%
    ) else (
        "C:\sendemail.exe" -f messages@mail -t admin@mail -u OK: SMART %COMPUTERNAME%
    )
) else (
    echo Can't find source file [%sSourceFile%].
    exit /b 1
)

endlocal
exit /b 0

10 (изменено: Rumata, 2014-11-27 13:54:44)

Re: CMD/BAT: Аналог bash на bat

Ваша задача на баше изначально написана сложно.

Вот перевод на cmd/bat


@echo off

set "filename=z.txt"

for /f "tokens=4,6" %%a in ( '
    find "Raw_Read_Error_Rate" ^<"%filename%
' ) do (
    if %%a lss %%b echo:%%a less %%b
)

Если будете поддерживать башевский вариант может быть стоит сделать так (2 варианта):


# variant 1: финт с возвратом кода (обратите внимание на восклицательный знак в коде awk)
# 0 - значит значение поля 4 меньше значения поля 6
# 1 - наоборот
if awk '/Raw_Read_Error_Rate/ { exit ! ( $4 < $6 ); } END { exit 1; }' "$filename"
then

# variant 2: в awk вычисляем разницу, а в шелле сравниваем с нулем
diff_4_6="$( awk '/Raw_Read_Error_Rate/ { print $4 - $6; }' "$filename" )"
if [ "$diff_4_6" -lt "0" ]
then

В мире юникс не любят делать двойную работу и если что-то можно сделать в одно действие. то поступают именно так. И еще, я бы не стал закладываться на то, что во входном файле строка с подстрокой Raw_Read_Error_Rate единственная. Думаю, что башизмов в примерах нет.

( 2 * b ) || ! ( 2 * b )

11

Re: CMD/BAT: Аналог bash на bat

что во входном файле строка с подстрокой Raw_Read_Error_Rate единственная.

Бывает несколько?

12 (изменено: Rumata, 2014-11-27 14:37:26)

Re: CMD/BAT: Аналог bash на bat

Не знаю. Наверно - нет. Скорее всего - нет. Данная фраза была сказана без вкладывания смысла в данный атрибут. В тот момент я не имел ввиду искомую подстроку вообще, хотя упомянул ее явно. Согласен - фраза спорная.

( 2 * b ) || ! ( 2 * b )

13

Re: CMD/BAT: Аналог bash на bat

Спасибо, взял вариант alexii с небольшими правками под себя.
Rumata ваш вариант может быть более логичен и правилен, но более понятный как-то удобней.

14

Re: CMD/BAT: Аналог bash на bat

mekok
Не то чтобы правильнее. Я бы сказал - экономичнее. Хотя в данном случае - повторно прочитать файл в 10 строк - не критично. В данном случае это даже экономия на спичках.
Когда надо обработать десяток многомегабайтных лог-файлов в поисках заданной строки, то задумываешься, как сократить собственное время ожидания завершения команды.

( 2 * b ) || ! ( 2 * b )

15

Re: CMD/BAT: Аналог bash на bat

Когда надо обработать десяток многомегабайтных лог-файлов в поисках заданной строки, то задумываешься, как сократить собственное время ожидания завершения команды.

+ открыть спойлер

Я уже не задумываюсь — LogParser наше всё .

16 (изменено: Rumata, 2014-11-27 23:42:39)

Re: CMD/BAT: Аналог bash на bat

logparser под юникс?

В довесок: обычно большие логи хранятся в сжатом вид, а штатных средств для работы с архивами и текстовыми файлами в виндоуз практически нет.

( 2 * b ) || ! ( 2 * b )

17

Re: CMD/BAT: Аналог bash на bat

logparser под юникс?

Нет конечно. Под Windows.

В довесок: обычно большие логи хранятся в сжатом вид,

Например? Не припоминаю такого.

а штатных средств для работы с архивами

Угу. Нет. Потому как см. выше: я не припоминаю таких логов.

текстовыми файлами в виндоуз практически нет.

WSH. PoSH.

18

Re: CMD/BAT: Аналог bash на bat

WSH. PoSH.

Штатным PowerShell стал начиная с семерки, WSH - более "штатный".

19

Re: CMD/BAT: Аналог bash на bat

Штатным PowerShell стал начиная с семерки,

Точнее — идущим в комплекте поставки.

20

Re: CMD/BAT: Аналог bash на bat

Точнее — идущим в комплекте поставки.

Если принципально, то - да, по сути - не столь важно.

21

Re: CMD/BAT: Аналог bash на bat

greg zakharov, сейчас сверился — таки да, Вы правы: «штатно» — именно оно, «идущее по штату», «состоящее в штатном расписании» и т.п.