LINUX.ORG.RU

Скрипт на bash с использованием whiptail

 , ,


0

1

В общем суть в чем, хочу написать маленький скрипт, который с использованием whiptail показывал жесткие диски. Накатал примерно такое:

#!/bin/bash

rm -f /tmp/tempfile
touch /tmp/tempfile
kdisk=$[$(fdisk -l | grep "Диск" | awk 'END {print NR}')+1]
nr=1
until [ $kdisk -eq $nr ]
do
disk=$(fdisk -l | grep "Диск" | awk NR==$nr)
echo \\ \"$disk\" \" \" >> /tmp/tempfile
nr=$[$nr+1]
done
k=`cat "/tmp/tempfile" | tr -s '\r\n' ' '`
OPTION=$(whiptail --title "test" --menu "test menu" 15 60 4 $k 3>&1 1>&2 2>&3)
exitstatus=$?
if [ $exitstatus = 0 ]; then
	echo $OPTION
else
	echo "fail"
fi
И все бы хорошо, да вот только whiptail мне показывает какую-то дикую ересь. А конкретно, он как-то неправильно обрабатывает переменную k. При этом если руками подставить вместо $k вывод полученный от cat «/tmp/tempfile» | tr -s '\r\n' ' ' , то все нормально отображает. И подскажите почему скрипт в centos 6 запускается, а вот в последней ubuntu он не работает.

Ужас какой. Такой плохой шеллскрипт ещё поискать.

Ну хотябы так можно делать:

#!/bin/bash
text=$(fdisk -l | grep "Диск" | awk '{printf "\\ \"%s\" \" \" ", $0}')
if OPTION=$(whiptail --title "test" --menu "test menu" 15 60 4 "$text"); then
	echo "$OPTION"
else
	echo "fail"
fi

Не работало у тебя из-за одной ошибки, но вообще их у тебя миллион, исправлять одну -только портить.

legolegs ★★★★★
()
Последнее исправление: legolegs (всего исправлений: 1)
Ответ на: комментарий от askoldmax

ну я и не проверял, у меня же нет виптейла ;D Возможно, эта галиматья 3>&1 1>&2 2>&3 всё-таки нужна и я зря её выкинул.

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

Я ее добавил и с ней тоже не работает. Вот за это

text=$(fdisk -l | grep "Диск" | awk '{printf "\\ \"%s\" \" \" ", $0}')
конечно спасибо.

Но суть проблемы осталась.

askoldmax
() автор топика
Ответ на: комментарий от legolegs

Возможно, эта галиматья 3>&1 1>&2 2>&3 всё-таки нужна и я зря её выкинул.

Нужна. У whiptail нет ключа --stdout, и вот это говно 3>&1 1>&2 2>&3 эффективно меняет местами stdout и stderr в whiptail. А это нужно потому как command substitution $() цепляет к пайпу stdout, а не stderr.

d_a ★★★★★
()

наверняка в $k есть еще всякие спецсимволы - может быть табы, или \n

перенаправь этот $k в файл и внимательно почитай в текстовом редакторе, что там за символы

может быть там какие-то проблемы с локалью и юникодом, сделай локаль на убунте в точности такой же как на центоси

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

В том-то и суть, что ничего там особого нет и если вставить например вместо $k

\ "Диск /dev/sdc: 14,5 GiB, 15597568000 байтов, 30464000 секторов" " "
То все прекрасно работает, но если эту же запись передавать через переменную, то уже ничего не работает.

askoldmax
() автор топика
Ответ на: комментарий от askoldmax

всю эту строчку (которую ты отправляешь на выполнение) заключи в кавычки, отправь в файл и прочитай, что там получилось

посимвольно сравни с тем, что надо

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

Это не php, $k поквочено должно быть надлежащим образом, чтобы уехало в whiptail одним аргументом.

d_a ★★★★★
()
Последнее исправление: d_a (всего исправлений: 1)
Ответ на: комментарий от stevejobs

Уже отправлял вот тут

echo \\ \"$disk\" \" \" >> /tmp/tempfile
Потом брал текст из этого tempfile и вставлял вместо $k, в этом случае работает идеально. Может я конечно кавычки не там ставлю, но я их как только уже не расставлял сегодня))

askoldmax
() автор топика
Ответ на: комментарий от askoldmax

я их как только уже не расставлял сегодня))

Вы их там наугад пытаетесь поставить что ли?


[d_a@home tmp]$ k=a\ b\ c
[d_a@home tmp]$ whiptail --title "test" --menu "test menu" 15 60 4 "$k" 'не нужно'

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

Возможно, это как раз тот редкий случай, когда кавычки вокруг $text не нужны.

Совсем в молоко :(

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

Да не наугад конечно, просто приведенный вариант уже далеко не первый. И все же, почему тогда не срабатывает такой вариант?

text=$(fdisk -l | grep "Диск" | awk '{printf "\\ \"%s\" \" \" ", $0}')
OPTION=$(whiptail --title "test" --menu "test menu" 15 60 4 "$text" 3>&1 1>&2 2>&3)
exitstatus=$?
if [ $exitstatus = 0 ]; then
	echo $OPTION
else
	echo "fail"
fi

Он на данный момент выглядит наиболее оптимальным.

askoldmax
() автор топика
Ответ на: комментарий от askoldmax

Потому что в --menu нужен ещё один аргумент, который вы потеряли.

OPTION=$(whiptail --title "test" --menu "test menu" 15 60 4 "$text" _______вот__это_______ 3>&1 1>&2 2>&3)

Я dialog/whiptail не пользуюсь, и не могу объяснить для чего он служит, читайте сами ман.

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

Он не потерян, в переменной он так же передается. Она выглядит примерно так

\ "Диск /dev/sdc: 14,5 GiB, 15597568000 байтов, 30464000 секторов" " "
То есть в идеале это должно выглядеть так
OPTION=$(whiptail --title "test" --menu "test menu" 15 60 4 \ "Диск /dev/sdc: 14,5 GiB, 15597568000 байтов, 30464000 секторов" " " 3>&1 1>&2 2>&3)

Спасибо за ответы

askoldmax
() автор топика
Ответ на: комментарий от askoldmax

Он не потерян, в переменной он так же передается. Она выглядит примерно так

\ «Диск /dev/sdc: 14,5 GiB, 15597568000 байтов, 30464000 секторов» " "

Проблема в том, что это три переменных

"$text" разворачивается в одну переменную, $text во столько, сколько внутри пробелов. Я-то думал whiptail просто строку там принимает со всем добром.

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

Не за что, мне же тоже интересно, иначе бы не сидел тут. Вот кстати, мой вариант (я всё же прочитал сам man whiptail):

[d_a@home tmp]$ IFS=$'\n' disks=($(printf '#\n%s\n' $(lsblk | grep -wE sd[a-z])))
[d_a@home tmp]$ whiptail --title "Диски" --menu "Выберите диск" 15 100 4 "${disks[@]}"

Вместо $(lsblk | grep -wE sd[a-z]) можно поставить что-нибудь своё. Мне было лень ковыряться с выхлопом fdisk (так как его от рута надо запускать).

http://i.imgur.com/0RNioiE.png

d_a ★★★★★
()
Последнее исправление: d_a (всего исправлений: 2)
Ответ на: комментарий от askoldmax

Проблема в том, что это три переменных

Вот теперь мне грустно стало.

Возьмите в помощь на будущее у меня вот эту функцию, незаменимая вещь пока будете изучать рассыпание в баше, ну и в отладке бывает полезна https://github.com/Jajauma/dotfiles/blob/master/bash/.bashrc#L96
и вот вам почитать http://mywiki.wooledge.org/BashGuide.

d_a ★★★★★
()
Последнее исправление: d_a (всего исправлений: 1)
Ответ на: комментарий от askoldmax

дело в том, что в 2017 году пользоваться башем, когда есть python, как-то не комильфо

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

есть где-то чудесная статья (сейчас не нагуглил, может кто подскажет?) которая наглядно доказывает, что никто не умеет пользоваться башем, ибо он состоит из сплошных костылей

у баша сейчас есть вполне конкретная область применения - использование на чужом сервере, про который ты ничего не знаешь, у тебя нет рута, и на который ты не можешь установить ничего другого (типа python, ruby, php, etc)

еще область применения - написание коротких программок-запускалок, с последующим сохранением куда-нибудь типа функций в ~/.bashrc

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

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

Чем бы отличалось запуск whiptail в python от bash? На самом bash тут почти ничего не писали, в основном запускали другие программы, которые удобней запускать именно из bash.

у баша сейчас есть вполне конкретная область применения - использование на чужом сервере, про который ты ничего не знаешь, у тебя нет рута, и на который ты не можешь установить ничего другого (типа python, ruby, php, etc)

python почти везде предустановлен и как заменить им bash даже если ты знаешь *чужой* сервер я не представляю.

Вообще не понимаю этой штуки — знаю python/ruby/php — зачем мне bash, всё перепишу на python/ruby/php. Для всего есть своя область применения.

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

Чем бы отличалось запуск whiptail в python от bash? На самом bash тут почти ничего не писали, в основном запускали другие программы, которые удобней запускать именно из bash.

то есть bash годится только для запуска других программ. а вместо whiptail может найтись подходящая библиотека или биндинг к оной.

Вообще не понимаю этой штуки — знаю python/ruby/php — зачем мне bash, всё перепишу на python/ruby/php.

чтобы не учить новый полоумный язык.

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

то есть bash годится только для запуска других программ. а вместо whiptail может найтись подходящая библиотека или биндинг к оной.

Я исхожу из того, что whiptail здесь в центре внимания, а всё остальное лишь обвязка. Если переписать это решение на python/ruby/php, то будет всё так же с вызовом другой программы внутри. Если искать подходящую библиотеку и не писать на полоумном языке, то задачу нужно иначе ставить.

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

Если переписать это решение на python/ruby/php, то будет всё так же с вызовом другой программы внутри.

если не видно разницы, то зачем учить больше?

anonymous
()
Ответ на: комментарий от conformist

знаю python/ruby/php — зачем мне bash,

проблема в том, что bash - очень, очень, очень плохой язык. Если ты не знаешь ничего кроме баша, стоит начать изучать прямо сейчас.

проблема топикстартера собственно и есть иллюстрация говенности баша

stevejobs ★★★★☆
()
Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от stevejobs

Я это всё понимаю, я говорю не об этом. Если мне нужно выполнить какую-то команду и потом распарсить её вывод, с чем хорошо справится awk или sed, то я наверняка выберу именно bash, потому что это проще, чем городить что-то с subprocess.call(command...) как в python. Т.е. для меня нецелесообразно вызывать команду из другого языка, когда я могу её напрямую вызвать в bash скрипте. И это я не защищаю bash, просто это удобнее в этом случае.

conformist ★★★
()

Чего-то эксперты начали решённый тред заполонять.

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

проблема в том, что bash - очень, очень, очень плохой язык.

У тебя очень очень однобокий подход. Оно и понятно - никнейм обязывает.

Баш, конечно, плохой _процедурный_ ЯП.

К счастью, он хороший потоковый язык.

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

Была у меня как-то железка на платформе ARM 2000-го года (EDGE/GPRS-роутер). Скрипты на BASH там если не летали, то весьма сносно выполнялись, но... какой-то идиот поставил туда пихтон. Так вот,пихтон там только запускался минуту-две, ну и работал потом соответственно.

А с точки зрения выразительности синтаксиса - считаю, что if/fi и case/esac в BASH - это замечательные, очень эстетичные и удобные конструкции, а в пихтоне то же самое отступами - просто феерически убого и уродливо. На вкус и цвет все фломастеры разные. Мне, например, не нравятся точки с запятой в конце строк на Perl'е, но... я понимаю, что конкретно для Perl они необходимы из-за «свободного синтаксиса», без этого нельзя было бы реализовать TWTOWTDI.

И уж если по существу вопроса: что BASH без внешнего Сишного кода бесполезен в общем-то (многое умеет, но мееедленно), что Python - абсолютно та же история! Нереально представить себе сложную программу на Python, которая бы не использовала скомпилированный код. Да ведь то же самое делает и BASH! Только вот найдите мне для Python код такого же уровня совершенства полировки, как код того же sed! Утилитами, которые вызывает BASH, пользуются все (т.е. 90% люди которые на BASH ничего не пишут), а компиленными либами пихтона - даже далеко не все пользователи пихтона. Посему в итоге качество бинарного кода, используемого в программах на Пихтон, зачастую на порядок хуже качества такого же кода в скриптах на BASH.

А насчёт ООП и прочего куриного дерьма - могу сказать только: жрите сами. Кстати, век пожирателей ООП уже подходит к концу: теперь рулит функциональный подход, который больше похож на пайпы в BASH, нежели на Г-объекты в Пихтон.

DRVTiny ★★★★★
()
Последнее исправление: DRVTiny (всего исправлений: 1)
Ответ на: комментарий от DRVTiny

Скрипты на BASH там если не летали, то весьма сносно выполнялись, но... какой-то идиот поставил туда пихтон.

Есть же dash. Опять же, евангелистам POSIX shell будет приятно (наверное).

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

дело в том, что в 2017 году пользоваться башем, когда есть python, как-то не комильфо

Не болтайте ерундой! (С) Покажи код на питоне, всех делов то. Но не покажешь. :) А так - будет ровным счётом то же самое :) Хотя заметь - против питона я ничего не имею, и даже наоборот.

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

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

Как раз таки проблема топикстартера может быть легко решена питоном, именно потому, что у whiptail такой интерфейс вызова. Принимал бы он stdin - намного легче бы было сделать всё на bash/dash/sh. Предложенный d_a вариант и так неплох, но вообще массивы - не сильное место баша и мне, например, было лень на них делать, курить ман на тему IFS и т.д.

legolegs ★★★★★
()
Последнее исправление: legolegs (всего исправлений: 1)
Ответ на: комментарий от legolegs

У BASH есть один «маленький» недостаток при работе с массивами: отсутствие ссылок во всех воплощениях, кроме самого примитивного - символическая ссылка на простой скаляр ( b=«a»; val_a=${!b} ). Конечно, для языка написания скриптов и это уже круто, но... без ссылок невозможны сколько-нибудь сложные структуры данных, и это доставляет немало неудобств. Зато BASH умеет

${HASH["iAmHashKey"]:+$((++HASH["iAmHashKey"]))}
Ну круто же! Разве нет?

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

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

Применительно к дизайну shell как максимально прямому (direct), насколько это возможно, интерфейсу человека к ядру ОС это неудобство того же уровня, как например отсутствие поддержки float point math и библиотек математических алгоритмов, например. Shell в вакууме -- это очень низкоровневый инструмент, с минимальным footprint и максимальной портируемостью для облегчения процесса переноса на новые платформы сразу после самого ядра.

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

но вообще массивы - не сильное место баша и мне, например, было лень на них делать

Можно и без массива, но придётся программировать явный цикл, а это типа, нечисто (в функциональном смысле), и к тому же не pure bash (xargs так-то в findutils сидит):

for x in /dev/sd[a-z]; do echo $x; sudo fdisk -l "$x" | grep "$x:"; done | xargs -d '\n' command args
Вместо моего отладочного command args только whiptail --info вставить :) Вот и до одной строчки сократили :)

d_a ★★★★★
()
Последнее исправление: d_a (всего исправлений: 1)
Ответ на: комментарий от d_a

только whiptail --info вставить

В смысле, --menu. Только не юзайте это :) Обработки ошибок нету, а без неё очень легко получить некогерентный вывод tag item tag item tag item ... , и менюшка развалится. Юзайте вариант с массивами, там такого нету, он функционально чист и вообще ня~н

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

отсутствие ссылок во всех воплощениях, кроме самого примитивного

Сложные структуры данных не юниксвейны :)

${#FFGH%&R#^&:,?(8!`H#($@N|/}
Ну круто же! Разве нет?

Нет :)

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

У BASH есть один «маленький» недостаток при работе с массивами: отсутствие ссылок во всех воплощениях, кроме самого примитивного - символическая ссылка на простой скаляр ( b=«a»; val_a=${!b} ). Конечно, для языка написания скриптов и это уже круто, но... без ссылок невозможны сколько-нибудь сложные структуры данных, и это доставляет немало неудобств.

получается bash может не хватить и все равно придется переписать

:+$((++

обсуфикация вместо человеческих имен

anonymous
()
Ответ на: комментарий от d_a

это неудобство того же уровня, как например отсутствие поддержки float point math и библиотек математических алгоритмов

давай массивы сюда же отнесем, чо уж

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

Не дам, массивы в сочетании с рекурсивными глобами (globstar) богоподобны, e.g srcs=(**/*.c) куда лучше чем find -print0, думаю никто не станет спорить, а вот, например, новоделы типа словарей из bash 4 (см. выше) это да, не пришей ни пристегни какое-то пошло.

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

Некрасиво же. Да и трудночитаемо. И непонятно, зачем нужно. Если бы оно самоинициализировалось нулём было бы полезно, так ведь нет же.

Алсо, зачем в srcs=(**/*.c) две звезды?

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

Алсо, зачем в srcs=(**/*.c) две звезды?

Чтобы во всех вложенных директориях тоже развернуло. Так-то стоковый glob только в текущей развернёт. Там, в том же vim например, неужто не делали никогда :vimgrep smth **/*.c?

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

кому-то для богоподобия не хватает float point math

А кому-то раковины. В то время как с точки зрения ядра float point абсолютная ересь, а shell просто повторяет кривизны kernel syscall плавные изгибы, и это правильно.

d_a ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.