Дело было вечером, делать было нечего, но дурная голова уркам покоя не давала… Данный пост создан как результат чисто-академического интереса. А началось все с того, что при разработке небольшого клиентского приложения для своих нужд, реализованного на Javascript, появилась необходимость взаимодействовать с уже существующей базой, где хранятся искомые данные. База — MySQL. Один из простых способов — реализация серверного скрипта (на PHP или еще каком языке), который по входящим параметрам делает нужный запрос и возвращает результат в JSON виде.
Другой вариант — это DBSlayer-прокси для MySQL. Кто про него не слышал, рассказываю в крадце: был создан в недрах New York Times как средство абстракции и балансирования нагрузки на БД. Подробнее можно почитать на сайте code.nytimes.com/projects/dbslayer/wiki/WhyUseIt. DBSlayer предоставляет API на основе JSON, известен в кругу NodeJS разработчиков.
Но это тоже не наш метод. Под катом приведено простое решение данной задачи на BASH.
Ну вот лень мне ставить было эту приблуду, да и задача, напомню, решается чисто для себя, никаких нагрузок и прочих радостей продакшн решений. Писать на PHP немного надоело, душа просила разнообразия и какого-нить выпендрежа. Решил сделатьс вою простую прослойку, в виде HTTP сервера на BASH, с реализацией нужного функционала.
Ни для кого не секрет, что Netcat в связке с дописыванием пары строк на баше можно превратить в WEB сервер. На хабре даже были посты про это. Взяв эту идею и доработав, мы можем получить простой аналог DBSlayer на коленке bash за пять минут.
От слов к действию...
Сначала напишем простую вспомогательную утилиту, для конвертирования вывода результатов из консольного клиента mysql в JSON формат:
cat ~/bin/mysql2json.sh
#!/bin/bash
sed -e 's/t/","/g'
-e 's/^/["/'
-e 's/$/"],/'
-e '1s/(.*)/{"fields":1 "data":[/g' -e '$s/.$/]}/'
| tr -d "n"
Используется она просто:
mysql -e "SELECT * FROM `mytable`" | ./mysql2json.sh
{"fields":["field_1","field_2","field_3"],"data":[["1","2","3"],["4","5","6"],["7","8","9"]]}
Теперь сам код сервера, который помещаем в файл dbjs.sh:
#!/bin/bash
:;while [ $? -eq 0 ]
do.
nc -vlp 8880 -c '(
r=read;
e=echo;
$r a b c;
z=$r;
while [ ${#z} -gt 2 ]
do.
$r z;
done;
f=`$e $b|sed 's/[^a-z0-9_.-]//gi'`;
h="HTTP/1.0";
o="$h 200 OKrn";
c="Content";
m="mysql -ulol -ptrololo"
m2j="~/bin/mysql2json.sh"
$e "$o$c-Type: text/json";
$e;
if [[ ( -n "$f" ) && ( "$f" != "favicon.ico" ) ]]
then.
$e "+ Connect to [$f]">&2;
db=${f%.*};
tb=${f#*.};
if [ "$tb" = "$db" ]
then
$e `$m ${db:-test} -e "show tables" | $m2j`;
else
$e `$m ${db:-test} -e "select * from $tb" | $m2j`;
fi;
else
$e `$m -e "show databases" | $m2j`;
fi
)';
done
Собственно и все. Запускаем и видим в консоли что-то вроде:
[ bash: ./dbjs.sh
listening on [any] 8880 ...
Далее просто обращаемся к нашему серверу, по указанному порту и получаем вывод:
// http://127.0.0.1:8880 - Выводит список баз данных
{
fields: [
"Database"
],
data: [
[ "information_schema" ],
[ "test" ]
]
}
// http://127.0.0.1:8880/test - Выводит список таблиц базы данных test
{
fields: [
"Tables_in_test"
],
data: [
["prods"],
["shops"],
["sp"],
["stat"]
]
}
// http://127.0.0.1:8880/test.shops - Выводит данные таблицы test.shops
{
"fields": [
"id",
"name",
"adress"
],
"data": [
["1","aaaaa",""],
["2","bbbbbbbbb",""],
["3","cccccccccccccccc","ccc"]
]
}
Скрипт не идеален, но никто не мешает его дорабатывать, если в этом вообще есть нужда.
П.С.: На вопрос: Зачем?, сразу отвечу: по фану. Жизнь должна приносит радость. Мне нравится получать позитив от таких вот нестандартных решений.
Автор: 0xy