LINUX.ORG.RU
ФорумAdmin

не работает символ | из переменной bash скрипта

 


0

2

есть вот такой скрипт

#!/bin/bash

execute="netstat -tulpn |grep 22"
cmpl2=$($execute)
echo $cmpl2

и после выполнения имеем вот это. как будто не отработал | grep 22 и как будто все в одну строку записалось

Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:29851 0.0.0.0:* LISTEN 1413/rmon tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 449/apache2 tcp 0 0 0.0.0.0:29852 0.0.0.0:* LISTEN 1413/rmon tcp 0 0 0.0.0.0:29853 0.0.0.0:* LISTEN 1413/rmon tcp 0 0 0.0.0.0:29854 0.0.0.0:* LISTEN 1413/rmon tcp 0 0 0.0.0.0:65534 0.0.0.0:* LISTEN 350/nrpe tcp 0 0 0.0.0.0:29855 0.0.0.0:* LISTEN 1413/rmon tcp 0 0 10.16.3.94:5667 0.0.0.0:* LISTEN 30542/nsca tcp 0 0 0.0.0.0:29803 0.0.0.0:* LISTEN 804/monsrv tcp 0 0 0.0.0.0:29807 0.0.0.0:* LISTEN 374/monsrv tcp 0 0 0.0.0.0:29809 0.0.0.0:* LISTEN 804/monsrv tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 439/sshd tcp 0 0 0.0.0.0:29813 0.0.0.0:* LISTEN 1414/mondn tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 439/sshd

пробовал execute=«netstat -tulpn |grep -v 22» и результат был один и тотже, то есть grep не отрабатывает.

подскажите как быть и что сделать?

в execute=«netstat -tulpn |grep 22» используются «» так как это в расширенной версии скрипта это массив, вида

cmd_action=(
"netstat -tulpn |grep 22"
"netstat -tulpn |grep 80"
"netstat -tulpn |grep 443"
"/usr/local/sbin/check_disk_usage.pl /"
"/usr/local/sbin/check_cpu_usage.pl all"
"/usr/local/sbin/check_mem_usage.pl free,all,swap"
)

и дальше по скрипту выбирается каждый элемент массива и исполняется с записью результата в переменную

но другие комманды успешно отрабатывают если в них нету символа |



Последнее исправление: diakon2 (всего исправлений: 2)

отрабатывает если сделать греп без пайпа. Но так понимаю нужен красивый однострочник?

[jtad@fedora:2 ~]$ grep 127 <<< $cmpl2
tcp        0      0 127.0.0.54:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      -                   
udp        0      0 127.0.0.54:53           0.0.0.0:*                           -                   
udp        0      0 127.0.0.53:53           0.0.0.0:*                           -                   
udp        0      0 127.0.0.1:323           0.0.0.0:*        

monkdt
()
Ответ на: комментарий от urxvt

Я имел ввиду, что Linux-окружение раздувается, и вместо православного grep городят фильтры в ss.

Твой нетстат с грепами на нагруженном сервере может несколько секунд работать, а то и дольше. ss тратит намного меньше ресурсов.

annulen ★★★★★
()

так как это в расширенной версии скрипта это массив, вида

Почему не оформить в функцию?

А так вообще можно сделать

execute="netstat -tulpn |grep 22"
cmpl2=$(sh -c "$execute")
echo $cmpl2
CrX ★★★★★
()
Ответ на: комментарий от urxvt

В основном да. Но grep тоже скорости не добавляет — выдачу ss тоже можно грепами фильтровать, и это будет несколько медленнее, особенно на системе с десятками тысяч активных соединений.

annulen ★★★★★
()
Ответ на: комментарий от urxvt

Ну понятно, что без вызова стороннего процесса это будет быстрей

Дело не только в стороннем процессе, а ещё и в фильтрации на стороне ядра, чтобы меньше данных в юзерспейс передавать.

annulen ★★★★★
()
Ответ на: комментарий от annulen

Жесть. Они эти запросы еще и в сисколы затащили. Передать из ядра пару килобайт данных не такая уж проблема, в данном контексте.

Ну понятно, что плюсы свои есть. С этим я не спорю. Просто, в очередной раз становится грустно, что все очень сильно усложняется.

urxvt ★★★★★
()
Ответ на: комментарий от urxvt

Они эти запросы еще и в сисколы затащили

Общение утилит iproute2 с ядром происходит по специальному протоколу через Netlink-сокеты. Так что сисколлов, принимающих фильтры в сигнатуре, в Linux нет. Netlink-сокеты, кстати, и в FreeBSD уже завезли)

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

Тем не менее, эти данные нужно скопировать, ядро и юзерспейс не могут использовать один и тот же буфер. А копирование требует не только времени, но и CPU. Проблема или нет — смотря насколько загружен проц и насколько часто дёргается ss.

annulen ★★★★★
()
Ответ на: комментарий от annulen

Кстати я пару раз наблюдал дикие тормоза ss -tnlp. Отрабатывал за 10сек (аж!), количество сокетов 1к. Кстати там и netstat -tnlp тоже тормозил. Я так и не понял причины.

Bers666 ★★★★★
()

но другие комманды успешно отрабатывают если в них нету символа |

шеллы не выполняют бесконечную рекурсию по поиску специальных конструкций, они делают ровно то, что сказано в документации - разбирают скрипт и выполняют ровно то что сказано. Так как ваши первые элементы массива команд вовсе не команды, а однострочные скрипты, то и надо ихх выполнять как скрипты. Тут предложили sh -c, но eval-ом будет быстрее. Ниже готовый пример решения, где элементы имеют префикс -e для вызова через eval, заодно наподумать вставлены две разновидности ls * и добавлены set -f в коде - может понадобиться, но всё равно придётся правильно и хорошо это поведение документировать.

#!/usr/bin/env bash

cmd_action=(
"-e netstat -tuln |grep 22"
"ls *"
"-e ls *"
)

for execute in "${cmd_action[@]}"; do
        if [[ $execute == -e\ * ]]; then
                cmpl2=$(eval "${execute#???}")
        else
                set -f
                cmpl2=$($execute)
                set +f
        fi

        echo "$cmpl2"
        echo
done

vodz ★★★★★
()