J'ai une sortie JSON à partir de laquelle j'ai besoin d'extraire quelques paramètres sous Linux.
Voici la sortie JSON :
{
"OwnerId": "121456789127",
"ReservationId": "r-48465168",
"Groups": [],
"Instances": [
{
"Monitoring": {
"State": "disabled"
},
"PublicDnsName": null,
"RootDeviceType": "ebs",
"State": {
"Code": 16,
"Name": "running"
},
"EbsOptimized": false,
"LaunchTime": "2014-03-19T09:16:56.000Z",
"PrivateIpAddress": "10.250.171.248",
"ProductCodes": [
{
"ProductCodeId": "aacglxeowvn5hy8sznltowyqe",
"ProductCodeType": "marketplace"
}
],
"VpcId": "vpc-86bab0e4",
"StateTransitionReason": null,
"InstanceId": "i-1234576",
"ImageId": "ami-b7f6c5de",
"PrivateDnsName": "ip-10-120-134-248.ec2.internal",
"KeyName": "Test_Virginia",
"SecurityGroups": [
{
"GroupName": "Test",
"GroupId": "sg-12345b"
}
],
"ClientToken": "VYeFw1395220615808",
"SubnetId": "subnet-12345314",
"InstanceType": "t1.micro",
"NetworkInterfaces": [
{
"Status": "in-use",
"SourceDestCheck": true,
"VpcId": "vpc-123456e4",
"Description": "Primary network interface",
"NetworkInterfaceId": "eni-3619f31d",
"PrivateIpAddresses": [
{
"Primary": true,
"PrivateIpAddress": "10.120.134.248"
}
],
"Attachment": {
"Status": "attached",
"DeviceIndex": 0,
"DeleteOnTermination": true,
"AttachmentId": "eni-attach-9210dee8",
"AttachTime": "2014-03-19T09:16:56.000Z"
},
"Groups": [
{
"GroupName": "Test",
"GroupId": "sg-123456cb"
}
],
"SubnetId": "subnet-31236514",
"OwnerId": "109030037527",
"PrivateIpAddress": "10.120.134.248"
}
],
"SourceDestCheck": true,
"Placement": {
"Tenancy": "default",
"GroupName": null,
"AvailabilityZone": "us-east-1c"
},
"Hypervisor": "xen",
"BlockDeviceMappings": [
{
"DeviceName": "/dev/sda",
"Ebs": {
"Status": "attached",
"DeleteOnTermination": false,
"VolumeId": "vol-37ff097b",
"AttachTime": "2014-03-19T09:17:00.000Z"
}
}
],
"Architecture": "x86_64",
"KernelId": "aki-88aa75e1",
"RootDeviceName": "/dev/sda1",
"VirtualizationType": "paravirtual",
"Tags": [
{
"Value": "Server for testing RDS feature in us-east-1c AZ",
"Key": "Description"
},
{
"Value": "RDS_Machine (us-east-1c)",
"Key": "Name"
},
{
"Value": "1234",
"Key": "cost.centre",
},
{
"Value": "Jyoti Bhanot",
"Key": "Owner",
}
],
"AmiLaunchIndex": 0
}
]
}
Je veux écrire un fichier qui contient un en-tête comme l'identifiant de l'instance, une balise comme le nom, le centre de coûts, le propriétaire. et en dessous de certaines valeurs de la sortie JSON. La sortie donnée ici n'est qu'un exemple.
Comment puis-je faire cela en utilisant sed
et awk
?
Résultat attendu :
Instance id Name cost centre Owner
i-1234576 RDS_Machine (us-east-1c) 1234 Jyoti
Réponse acceptée :
La disponibilité d'analyseurs dans presque tous les langages de programmation est l'un des avantages de JSON en tant que format d'échange de données.
Plutôt que d'essayer d'implémenter un analyseur JSON, il est probablement préférable d'utiliser un outil conçu pour l'analyse JSON tel que jq ou un langage de script à usage général doté d'une bibliothèque JSON.
Par exemple, en utilisant jq, vous pouvez extraire l'ImageID du premier élément du tableau Instances comme suit :
jq '.Instances[0].ImageId' test.json
Alternativement, pour obtenir les mêmes informations en utilisant la bibliothèque JSON de Ruby :
ruby -rjson -e 'j = JSON.parse(File.read("test.json")); puts j["Instances"][0]["ImageId"]'
Je ne répondrai pas à toutes vos questions et commentaires révisés, mais ce qui suit est, espérons-le, suffisant pour vous aider à démarrer.
Supposons que vous disposiez d'un script Ruby capable de lire un STDIN et de générer la deuxième ligne dans votre exemple de sortie[0]. Ce script pourrait ressembler à :
#!/usr/bin/env ruby
require 'json'
data = JSON.parse(ARGF.read)
instance_id = data["Instances"][0]["InstanceId"]
name = data["Instances"][0]["Tags"].find {|t| t["Key"] == "Name" }["Value"]
owner = data["Instances"][0]["Tags"].find {|t| t["Key"] == "Owner" }["Value"]
cost_center = data["Instances"][0]["SubnetId"].split("-")[1][0..3]
puts "#{instance_id}t#{name}t#{cost_center}t#{owner}"
Comment pourriez-vous utiliser un tel script pour accomplir tout votre objectif ? Eh bien, supposons que vous disposiez déjà des éléments suivants :
- une commande pour lister toutes vos instances
- une commande pour obtenir le json ci-dessus pour n'importe quelle instance de votre liste et le sortir vers STDOU
Une façon serait d'utiliser votre shell pour combiner ces outils :
echo -e "Instance idtNametcost centretOwner"
for instance in $(list-instances); do
get-json-for-instance $instance | ./ugly-ruby-scriptrb
done
Maintenant, vous avez peut-être une seule commande qui vous donne un blob json pour toutes les instances avec plus d'éléments dans ce tableau "Instances". Eh bien, si tel est le cas, vous aurez juste besoin de modifier un peu le script pour parcourir le tableau plutôt que d'utiliser simplement le premier élément.
En fin de compte, la façon de résoudre ce problème est la façon de résoudre de nombreux problèmes sous Unix. Décomposez-le en problèmes plus faciles. Trouvez ou écrivez des outils pour résoudre le problème le plus facile. Combinez ces outils avec votre shell ou d'autres fonctionnalités du système d'exploitation.
[0] Notez que je n'ai aucune idée d'où vous obtenez le centre de coûts, donc je l'ai inventé.