
Дело было вечером, делать было нечего, но дурная голова уркам покоя не давала… Данный пост создан как результат чисто-академического интереса. А началось все с того, что при разработке небольшого клиентского приложения для своих нужд, реализованного на 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 на
От слов к действию...
Сначала напишем простую вспомогательную утилиту, для конвертирования вывода результатов из консольного клиента 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 OK\r\n"; 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"] ] }
Скрипт не идеален, но никто не мешает его дорабатывать, если в этом вообще есть нужда.
П.С.: На вопрос: Зачем?, сразу отвечу: по фану. Жизнь должна приносит радость. Мне нравится получать позитив от таких вот нестандартных решений.