Apache работает как непривилегированный пользователь, известный как www-data
, в дистрибутивах Debian по весьма уважительной причине: безопасность.
Это считается хорошей практикой безопасности при работе с демонами, отказывающимися от прав привилегий, избегая, насколько это возможно, создания файлов конфигурации или файлов данных с владельцем непривилегированного пользователя, который запускает демон - как таковой, если Пользователь Apache скомпрометирован, злоумышленникам будет гораздо сложнее возиться с вещами или испортить сайт.
По возможности рекомендую создавать сайты с разными пользователями, а права чтения давать только группе www-data; и иметь доступ на запись к www-данным только в каталогах, которые действительно в них нуждаются. Однако даже этого можно избежать с помощью mod-ruid2.
mod-ruid2 позволяет фактически запускать каждый сайт / виртуальный хост вместе с их владельцем, и работать с моделью безопасности страниц намного проще. Это устраняет необходимость создания всемирных каталогов с возможностью записи. Это также гарантирует, что в случае компрометации одного виртуального хоста злоумышленник не сможет внедрить вредоносное ПО в другие виртуальные хосты.
mod-ruid2 также рекомендуется для людей с моделью хостинга, и мы используем его здесь для запуска нескольких сотен сайтов, что весьма успешно.
К сожалению, документации по mod-ruid2 немного, и мне пришлось написать более подробный пост, чтобы описать его здесь, в Unix и Linux .
Предполагая, что у вас всегда есть логин и значение в двойных кавычках, следующих друг за другом без пробелов, вот конструкция для grep и подсчета:
grep -o 'login":"[^"]*"' * | cut -d'"' -f3 | sort | uniq -c
Это создаст список входов в систему с количеством вхождений.
Теперь нам нужно сформировать из него нужный вам формат json. sed
может сделать это за вас:
| sed '1i{
s/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/;$a}'
Здесь sed
поместит {
в начало блока и }
в его конец и изменит вывод uniq
на ожидаемый формат json.
UPD :В итоге итоговая команда должна выглядеть так:
grep -o 'login":"[^"]*"' * | cut -d'"' -f3 | sort | uniq -c | sed '1i{
s/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/;$a}' > file.txt
@rush использование sed
не работало в моей оболочке, поэтому я пошел по этому пути
grep -Poh '(?<=login":")[^"]*' json* | sort | uniq -c | awk -v OFS=': ' 'BEGIN{print "{"}{print $2, $1}END{print"}"}' | sed -E 's/([0-9])$/\1,/g;s/:/\":/g;s/^([^{}])/\"\1/g'
Множественное число sed
можно изменить, если ваша оболочка позволяет экранировать "
и печатать их в операторе awk
.
grep -Poh '(?<=login":")[^"]*' json* | sort | uniq -c | awk -v OFS=': ' 'BEGIN{print "{"}{print \"$2\", $1}END{print"}"}' | sed -E 's/([0-9])$/\1,/g'
У меня в оболочке awk
подавился \"
во втором скрипте. Не уверен, почему, но уверен, что кто-то там скажет мне.
Я также пробовал jq
, но он задыхался от файлов json. Синтаксическая ошибка
"this":"is' #is written so I edited these to
"this":"is"
Также jq
не понравилась конструкция
{"a":"strange"} # so I also edited these to
b: {"a":"strange"}
Если исходные файлы должны соответствовать внесенным изменениям, тогда jq
работает
jq '.login' json* | sort | uniq -c | awk -v OFS=': ' 'BEGIN{print "{"}{print $2, $1}END{print"}"}' | sed -E 's/([0-9])$/\1,/g'
Чтобы получить все имена пользователей, т. е. всю строку, связанную с ключом login
, из правильно сформированного документа JSON , не зная структуры документа:
jq -r '..|select(.login?).login' file.json
Применение этого к нескольким файлам JSON, а также сортировка и подсчет результата:
jq -r '..|select(.login?).login' *.json | sort | uniq -c
Здесь используется выражение jq
..
:Повторный просмотр всех ключей и значений. select(.login?)
:Выберите обнаруженные объекты, содержащие ключ login
. .login
:Получите значение для этого ключа. Словарь, который вы хотели бы иметь, основанный на приведенном выше jq
выражении:
jq -sr '[..|select(.login?).login]|group_by(.)|map({key:.[0],value:length})|from_entries' *.json
Тестирование:
$ cat file.json
{"this":"is", "A":{"login":"username2"}, "type":{"of":"object", "but":"please"},
"go":"withit", "login":"me"}
$ jq -sr '[..|select(.login?).login]|group_by(.)|map({key:.[0],value:length})|from_entries' file.json
{
"me": 1,
"username2": 1
}
Дважды передать один и тот же файл:
$ jq -sr '[..|select(.login?).login]|group_by(.)|map({key:.[0],value:length})|from_entries' file.json f
ile.json
{
"me": 2,
"username2": 2
}
Используйте jq
с -c
для получения однострочного компактного вывода.
Для нашего примера файла jq -sr '[..|select(.login?).login]' file.json
даст
[
"me",
"username2"
]
Прохождение через group_by(.)
дает
[
[
"me"
],
[
"username2"
]
]
Часть map({key:.[0],value:length})
дает
[
{
"key": "me",
"value": 1
},
{
"key": "username2",
"value": 1
}
]
и from_entries
в конце дают окончательный результат.
Как насчет использования perl-хэша с ключом для совпадения с регулярным выражением, который вы можете преобразовать с помощью модуля JSON:
$ perl -MJSON -lne '$h{$1}++ for /(?<="login":")(.*?)(?=")/g }{ print encode_json \%h' file1 file2
{"username3":1,"username2":1,"username1":2}