使用gcloud命令优化我的bash脚本 [英] optimize my bash script with gcloud commands

查看:70
本文介绍了使用gcloud命令优化我的bash脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您能帮我为我优化此脚本吗?这是从我们整个组织中获取的所有元数据,当前此脚本需要12到13个小时之间的任何时间才能完成.但是我想每周运行多次,是否有办法对其进行优化并更快地获得结果?

Could you help me with optimizing this script for me? This is grabbing all the meta data from our total organization and currently this script takes any where between 12-13 hours to complete. But I want to run this multiple times a weeks, is there a way to optimize it and get the results faster?

#!/usr/bin/env bash
PROJECTS=$(gcloud projects list --format='get(projectId)')
FILE="instances.csv"
rm $FILE
touch $FILE
START_TIME=$SECONDS
COUNTER=1
TOTAL=0
echo 'name,organization,space,zone,machine_type,preemptible,internal_ip,external_ip,status,service_account,project_id' >> $FILE
for project_id in $PROJECTS
do
  ((TOTAL=TOTAL+1))
done
for project_id in $PROJECTS
do
  echo 'project ' $COUNTER 'of' $TOTAL
  echo $project_id
  ORG=$(gcloud projects describe $project_id --format="get(labels.organization)")
  echo $ORG
  SPACE=$(gcloud projects describe $project_id --format="get(labels.space)")
  echo $SPACE
  gcloud compute instances list --project $project_id --format="csv(
   name,
   format("$ORG",''),
   format("$SPACE", ''),
   zone.basename(),
   machineType.machine_type().basename(),
   scheduling.preemptible.yesno(yes=true, no=''),
   networkInterfaces[].networkIP.notnull().list():label=INTERNAL_IP,
   networkInterfaces[].accessConfigs[0].natIP.notnull().list():label=EXTERNAL_IP,
   status,
   serviceAccounts[0].email
  )" | awk 'NR>1' | sed s/$/,$project_id/ >> $FILE
  ((COUNTER=COUNTER+1))
  ELAPSED_TIME=$(($SECONDS - $START_TIME))
  echo 'Elapsed time -' "$(($ELAPSED_TIME/60)) min $(($ELAPSED_TIME%60)) sec"
done
ELAPSED_TIME=$(($SECONDS - $START_TIME))
  echo 'Elapsed time -' "$(($ELAPSED_TIME/60)) min $(($ELAPSED_TIME%60)) sec"

推荐答案

我发现挑战很有趣,尤其是在Go中并发的情况下.

I found the challenge interesting, especially with concurrency in Go, and I made it.

package main

import (
    "context"
    "fmt"
    "google.golang.org/api/cloudresourcemanager/v1"
    "google.golang.org/api/compute/v1"
    "net/http"
    "strings"
    "sync"
)

var listSeparator = ";"

func main() {
    http.HandleFunc("/", ListProject)
    http.ListenAndServe(":8080", nil)
}

func ListProject(w http.ResponseWriter, r *http.Request) {
    ctx := context.Background()
    svc, err := cloudresourcemanager.NewService(ctx)
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    svcCompute, err := compute.NewService(ctx)
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    prjlist, err := svc.Projects.List().Do()
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        return
    }

    waitGroup := &sync.WaitGroup{}
    c := make(chan line)
    finished := make(chan string)

    waitGroup.Add(len(prjlist.Projects))

    for _, prj := range prjlist.Projects {
        go listInstances(*prj, svcCompute, c, waitGroup)
    }
    go func() {
        waitGroup.Wait()
        finished <- ""
    }()

    fmt.Fprint(w, "name,organization,space,zone,machine_type,preemptible,internal_ip,external_ip,status,service_account,project_id\n")

    loop:
        for {
            select {
            case l := <-c:
                fmt.Fprintf(w, "%s,%s,%s,%s,%s,%t,%s,%s,%s,%s,%s\n", l.projectName,l.organization,l.space,l.zone,l.machineType,l.preemtible,l.internalIps,l.externalIps,l.status,l.serviceAccount,l.projectId)
            case <- finished:
                break loop
            }
        }
}

func listInstances(prj cloudresourcemanager.Project, svcCompute *compute.Service, c chan line, group *sync.WaitGroup) {
    defer group.Done()

    zoneList, err := svcCompute.Zones.List(prj.ProjectId).Do()
    if err != nil {
        fmt.Println(err)
        return
    }

    group.Add(len(zoneList.Items))

    for _, zone := range zoneList.Items {
        go listInstanceInZone(*zone, prj, svcCompute, c, group)
    }
}

func listInstanceInZone(zone compute.Zone, prj cloudresourcemanager.Project, svcCompute *compute.Service, c chan line, group *sync.WaitGroup) {
    defer group.Done()
    instList, err := svcCompute.Instances.List(prj.ProjectId, zone.Name).Do()
    if err != nil {
        fmt.Println(err)
        return
    }
    for _, inst := range instList.Items {

        internalIps := ""
        externalIps := ""

        for _, n := range inst.NetworkInterfaces {
            for _, a := range n.AccessConfigs {
                if externalIps != "" {
                    externalIps += listSeparator
                }
                externalIps += a.NatIP
            }
            if internalIps != "" {
                internalIps += listSeparator
            }
            internalIps += n.NetworkIP
        }

        sacEmails := ""
        for _, s := range inst.ServiceAccounts {
            if sacEmails != "" {
                sacEmails += listSeparator
            }
            sacEmails += s.Email
        }

        machineTypeLastIndex := strings.LastIndex(inst.MachineType,"/")
        l := line{
            projectName:    prj.Name,
            projectId:      prj.ProjectId,
            organization:   prj.Labels["labels.organization"],
            space:          prj.Labels["labels.space"],
            zone:           zone.Name,
            machineType:    inst.MachineType[machineTypeLastIndex+1:],
            preemtible:     inst.Scheduling.Preemptible,
            internalIps:    internalIps,
            externalIps:    externalIps,
            status:         inst.Status,
            serviceAccount: sacEmails,
        }
        c <- l
    }

}

type line struct {
    projectName    string
    projectId      string
    organization   string
    space          string
    zone           string
    machineType    string
    preemtible     bool
    internalIps    string
    externalIps    string
    status         string
    serviceAccount string
}

在预期结果中可能会更优雅,或有一些问题,但是它可以在几秒钟内而不是几分钟内工作(无并发性)

There might have more elegant, or some issue in the expected results, but it works in few seconds instead of few minutes (without concurrency)

这篇关于使用gcloud命令优化我的bash脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆