getent passwd以正确格式作为json输出
我使用jq是为了尝试将bash命令输出转换为json。但是,转换失败了 使用此行:getent passwd以正确格式作为json输出,json,linux,bash,shell,format,Json,Linux,Bash,Shell,Format,我使用jq是为了尝试将bash命令输出转换为json。但是,转换失败了 使用此行: hostname && getent passwd | egrep -v '/s?bin/(nologin|shutdown|sync|halt)' | cut -d: -f1 | sudo xargs -I % sh -c 'echo %; chage -l %; echo' | jq --raw-input . | jq --slurp . 主机名必须是json的根元素 用户名必须是第一
hostname && getent passwd | egrep -v '/s?bin/(nologin|shutdown|sync|halt)' | cut -d: -f1 | sudo xargs -I % sh -c 'echo %; chage -l %; echo' | jq --raw-input . | jq --slurp .
- 主机名必须是json的根元素
- 用户名必须是第一个元素
- getent passwd输出必须是username的子元素
有人试过将bash输出正确地转换为json吗?谢谢这里有一个perl脚本,它以JSON格式显示
/etc/passwd
的主机名和内容(顺便说一句,在我熟悉的任何操作系统上,输出看起来都不像您的示例。)
请注意,当谈论JSON对象的键时,“第一个元素”当然毫无意义;它们是无序的。如果您依赖于对象中特定位置的特定键,那么您就做错了
#/usr/bin/env perl
使用警告;
严格使用;
使用Sys::Hostname;
使用User::pwent;
#可能必须通过操作系统的软件包管理器或
#和你最喜欢的CPAN客户端
使用JSON;
我的%pwdb=(主机名=>hostname(),用户=>[]);
while(my$pw=getpwent){
#忽略具有特定shell的用户
下一个如果
定义了$pw->shell&&$pw->shell=~m!s?bin/(nologin | shutdown | sync | halt)!;
推送{$pwdb{“用户”}{
用户名=>$pw->name,
详细信息=>{
passwd=>$pw->passwd,
uid=>$pw->uid,
gid=>$pw->gid,
更改=>$pw->更改,
年龄=>$pw->年龄,
配额=>$pw->配额,
comment=>$pw->comment,
class=>$pw->class,
gecos=>$pw->gecos,
dir=>$pw->dir,
外壳=>$pw->外壳,
expire=>$pw->expire
}
};
}
我的$pp=JSON->new->ascii->pretty;
打印$pp->编码(\%pwdb);
我在用jq
我意识到jq
在这里很受欢迎,但我将推荐这项任务。虽然Xidel主要是一个HTML/XML/JSON解析器(使用CSS、XPath、XQuery、JSONiq和模式模板),但它也可以处理基本文本 你说你想要一个像这样的json:
{
“主机名”:“示例”,
“用户”:[
{
“用户名”:“示例1”,
“详情”:{
“LastPasswordChange”:“2018年11月12日”,
“PasswordExpires”:“从不”,
“PasswordInactive”:“从不”,
“AccountExpires”:“从不”,
“MindaysBetween密码更改”:“0”,
“MaxDaysBetween密码更改”:“99999”,
密码过期前的警告天数:“7”
}
},
{
“用户名”:“示例2”,
“详情”:{
“LastPasswordChange”:“2018年11月13日”,
“PasswordExpires”:“从不”,
“PasswordInactive”:“从不”,
“AccountExpires”:“从不”,
“MindaysBetween密码更改”:“0”,
“MaxDaysBetween密码更改”:“99999”,
密码过期前的警告天数:“7”
}
}
]
}
这意味着users
数组需要分别为每个用户填充对象(根据chage
程序的输出创建)。这就是为什么我会选择另一种方法
比如说getent passwd | egrep-v'/s?bin/(nologin | shutdown | sync | halt)| cut-d:-f1
返回:
root
user1
user2
我们将通过管道连接到Xidel,首先创建一个基本json:
getent passwd | egrep -v '/s?bin/(nologin|shutdown|sync|halt)' | cut -d: -f1 | xidel -s - --xquery '
{
"hostname":"'$(hostname)'",
"users":x:lines($raw) ! {
"username":.
}
}
'
- 在原始命令前面不需要使用
,因为您只需从Xidel中调用它(这也使得查询更加容易)hostname&&
- 使用
可以从Xidel的输入(本例中为stdin)创建每一行的序列。另一个可使用的函数是x:lines($raw)
标记化($raw,“\n”)
{
"hostname": "user",
"users": [
{
"username": "root"
},
{
"username": "user1"
},
{
"username": "user2"
}
]
}
{
"hostname": "user",
"users": [
{
"username": "root",
"details": {
"Last password change": "never",
"Password expires": "never",
"Password inactive": "never",
"Account expires": "never",
"Minimum number of days between password change": "0",
"Maximum number of days between password change": "99999",
"Number of days of warning before password expires": "7"
}
},
{
"username": "user1",
"details": {
"Last password change": "never",
"Password expires": "never",
"Password inactive": "never",
"Account expires": "never",
"Minimum number of days between password change": "0",
"Maximum number of days between password change": "99999",
"Number of days of warning before password expires": "7"
}
},
{
"username": "user2",
"details": {
"Last password change": "Oct 23, 2018",
"Password expires": "never",
"Password inactive": "never",
"Account expires": "never",
"Minimum number of days between password change": "0",
"Maximum number of days between password change": "99999",
"Number of days of warning before password expires": "7"
}
}
]
}
{
"hostname": "user",
"users": [
{
"username": "root",
"details": {
"LastPasswordChange": "never",
"PasswordExpires": "never",
"PasswordInactive": "never",
"AccountExpires": "never",
"MinimumNumberOfDaysBetweenPasswordChange": 0,
"MaximumNumberOfDaysBetweenPasswordChange": 99999,
"NumberOfDaysOfWarningBeforePasswordExpires": 7
}
},
{
"username": "user1",
"details": {
"LastPasswordChange": "never",
"PasswordExpires": "never",
"PasswordInactive": "never",
"AccountExpires": "never",
"MinimumNumberOfDaysBetweenPasswordChange": 0,
"MaximumNumberOfDaysBetweenPasswordChange": 99999,
"NumberOfDaysOfWarningBeforePasswordExpires": 7
}
},
{
"username": "user2",
"details": {
"LastPasswordChange": "Oct 23, 2018",
"PasswordExpires": "never",
"PasswordInactive": "never",
"AccountExpires": "never",
"MinimumNumberOfDaysBetweenPasswordChange": 0,
"MaximumNumberOfDaysBetweenPasswordChange": 99999,
"NumberOfDaysOfWarningBeforePasswordExpires": 7
}
}
]
}
接下来,我们将从Xidel中调用chage
,以创建details
对象:
getent passwd | egrep -v '/s?bin/(nologin|shutdown|sync|halt)' | cut -d: -f1 | xidel -s - --xquery '
{
"hostname":"'$(hostname)'",
"users":x:lines($raw) ! {
"username":.,
"details":{|
for $x in x:lines(
system(x"chage -l {.}")
)
let $a:=tokenize(
$x,
":"
)
return {
normalize-space($a[1]):normalize-space($a[2])
}
|}
}
}
'
返回system(x“chage-l{.}”)
、chage-l root
和chage-l user1
的输出chage-l user2
- 使用
在其周围再次创建每一行的序列。x:lines()
输出的第一行,例如:user2
- 对于此序列(或行)中的每个项目,将创建变量
,该变量将此项目的序列一分为二,并以$a
作为分隔符<代码>$a因此,对于第一项::
- 最后创建属性值对,并规范化空白:
{
"hostname": "user",
"users": [
{
"username": "root"
},
{
"username": "user1"
},
{
"username": "user2"
}
]
}
{
"hostname": "user",
"users": [
{
"username": "root",
"details": {
"Last password change": "never",
"Password expires": "never",
"Password inactive": "never",
"Account expires": "never",
"Minimum number of days between password change": "0",
"Maximum number of days between password change": "99999",
"Number of days of warning before password expires": "7"
}
},
{
"username": "user1",
"details": {
"Last password change": "never",
"Password expires": "never",
"Password inactive": "never",
"Account expires": "never",
"Minimum number of days between password change": "0",
"Maximum number of days between password change": "99999",
"Number of days of warning before password expires": "7"
}
},
{
"username": "user2",
"details": {
"Last password change": "Oct 23, 2018",
"Password expires": "never",
"Password inactive": "never",
"Account expires": "never",
"Minimum number of days between password change": "0",
"Maximum number of days between password change": "99999",
"Number of days of warning before password expires": "7"
}
}
]
}
{
"hostname": "user",
"users": [
{
"username": "root",
"details": {
"LastPasswordChange": "never",
"PasswordExpires": "never",
"PasswordInactive": "never",
"AccountExpires": "never",
"MinimumNumberOfDaysBetweenPasswordChange": 0,
"MaximumNumberOfDaysBetweenPasswordChange": 99999,
"NumberOfDaysOfWarningBeforePasswordExpires": 7
}
},
{
"username": "user1",
"details": {
"LastPasswordChange": "never",
"PasswordExpires": "never",
"PasswordInactive": "never",
"AccountExpires": "never",
"MinimumNumberOfDaysBetweenPasswordChange": 0,
"MaximumNumberOfDaysBetweenPasswordChange": 99999,
"NumberOfDaysOfWarningBeforePasswordExpires": 7
}
},
{
"username": "user2",
"details": {
"LastPasswordChange": "Oct 23, 2018",
"PasswordExpires": "never",
"PasswordInactive": "never",
"AccountExpires": "never",
"MinimumNumberOfDaysBetweenPasswordChange": 0,
"MaximumNumberOfDaysBetweenPasswordChange": 99999,
"NumberOfDaysOfWarningBeforePasswordExpires": 7
}
}
]
}
你可以更进一步:
getent passwd | egrep -v '/s?bin/(nologin|shutdown|sync|halt)' | cut -d: -f1 | xidel -s - --xquery '
{
"hostname":"'$(hostname)'",
"users":x:lines($raw) ! {
"username":.,
"details":{|
for $x in x:lines(
system(x"chage -l {.}")
)
let $a:=tokenize(
$x,
":"
)
return {
string-join(
for $x in tokenize(
normalize-space($a[1]),
" "
)
return
upper-case(
substring(
$x,
1,
1
)
)||substring(
$x,
2
)
):normalize-space($a[2]) ! (
if (. castable as decimal) then
number(.)
else
.
)
}
|}
}
}
'
- 不是上次更改密码,而是
LastPasswordChange
- 而不是
(一个字符串),使用“99999”
99999
查询输出:
{
"hostname": "user",
"users": [
{
"username": "root"
},
{
"username": "user1"
},
{
"username": "user2"
}
]
}
{
"hostname": "user",
"users": [
{
"username": "root",
"details": {
"Last password change": "never",
"Password expires": "never",
"Password inactive": "never",
"Account expires": "never",
"Minimum number of days between password change": "0",
"Maximum number of days between password change": "99999",
"Number of days of warning before password expires": "7"
}
},
{
"username": "user1",
"details": {
"Last password change": "never",
"Password expires": "never",
"Password inactive": "never",
"Account expires": "never",
"Minimum number of days between password change": "0",
"Maximum number of days between password change": "99999",
"Number of days of warning before password expires": "7"
}
},
{
"username": "user2",
"details": {
"Last password change": "Oct 23, 2018",
"Password expires": "never",
"Password inactive": "never",
"Account expires": "never",
"Minimum number of days between password change": "0",
"Maximum number of days between password change": "99999",
"Number of days of warning before password expires": "7"
}
}
]
}
{
"hostname": "user",
"users": [
{
"username": "root",
"details": {
"LastPasswordChange": "never",
"PasswordExpires": "never",
"PasswordInactive": "never",
"AccountExpires": "never",
"MinimumNumberOfDaysBetweenPasswordChange": 0,
"MaximumNumberOfDaysBetweenPasswordChange": 99999,
"NumberOfDaysOfWarningBeforePasswordExpires": 7
}
},
{
"username": "user1",
"details": {
"LastPasswordChange": "never",
"PasswordExpires": "never",
"PasswordInactive": "never",
"AccountExpires": "never",
"MinimumNumberOfDaysBetweenPasswordChange": 0,
"MaximumNumberOfDaysBetweenPasswordChange": 99999,
"NumberOfDaysOfWarningBeforePasswordExpires": 7
}
},
{
"username": "user2",
"details": {
"LastPasswordChange": "Oct 23, 2018",
"PasswordExpires": "never",
"PasswordInactive": "never",
"AccountExpires": "never",
"MinimumNumberOfDaysBetweenPasswordChange": 0,
"MaximumNumberOfDaysBetweenPasswordChange": 99999,
"NumberOfDaysOfWarningBeforePasswordExpires": 7
}
}
]
}
“美化”查询更容易阅读,但如果您更喜欢“精简”版本:
好的,我知道你想要的输出来自哪里;此更改程序,而不是passwd数据库。在你的问题中,你真的应该更清楚这一点。我会在有机会的时候更新我的答案。谢谢你的回答。我在某个地方找到了命令,但还不太擅长bash。这就是为什么我不能说得更清楚。你能给我们看一下主机名和getent passwd | egrep-v'/s?bin/(nologin | shutdown | sync | halt)| cut-d:-f1 | sudo xargs-i%sh-c'echo%;查格-1%;回显“(密码被屏蔽)?当然。输出现在添加到上面。哇。T