How to sort by name `docker service ls`

2019-09-15 17:25发布

问题:

I'm using Docker Swarm 1.13.1 and it would be very practical to list services by name (A-Z).

I don't think Docker support this feat by natively so I expect some awk, sort and other little hacks.

So far this is the closest I can get:

root@N01-par1-dev-e:~/deploy-setup# docker service ls | sort -k2,2 -k1
yru8n6zxmp08  consul            global      4/4       consul:latest
1lb98n83fttr  mysql             replicated  1/1       devmtl/percona-fire:5.7.16-10-1
ID            NAME              MODE        REPLICAS  IMAGE
i75t4zef8x8c  papertrail        global      4/4       gliderlabs/logspout:latest
4s14t7f13fp8  portainer         replicated  1/1       portainer/portainer:1.11.3
8wojufyq3dwn  resilio           global      4/4       devmtl/resilio-fire:2.4.4-alpine-0
vn8fhhfvb6pw  sematext          global      4/4       sematext/sematext-agent-docker:1.31.11
mwxtlff6jyl5  thm-s0001-iamfoo  replicated  1/1       devmtl/iam-this-ctn:1.0.1-alpine-0
o8p4q85axkwy  thm-s0002-iambar  replicated  1/1       devmtl/iam-this-ctn:1.0.1-alpine-0
wedrfqzkg3zp  thm-s0003-caply   replicated  1/1       devmtl/nginx-fire:1.10.3-alpine-0
ql9yapc0brnk  thm-s0003-valgo   replicated  1/1       devmtl/caddy:0.9.5-alpine-0
vu3jhyo71oos  traefik           replicated  1/1       traefik:v1.1.2-alpine

or ...

root@N01-par1-dev-e:~/deploy-setup# docker service ls | tail -n +2 |  sort -k2,2 -k1
yru8n6zxmp08  consul            global      4/4       consul:latest
1lb98n83fttr  mysql             replicated  1/1       devmtl/percona-fire:5.7.16-10-1
i75t4zef8x8c  papertrail        global      4/4       gliderlabs/logspout:latest
4s14t7f13fp8  portainer         replicated  1/1       portainer/portainer:1.11.3
8wojufyq3dwn  resilio           global      4/4       devmtl/resilio-fire:2.4.4-alpine-0
vn8fhhfvb6pw  sematext          global      4/4       sematext/sematext-agent-docker:1.31.11
mwxtlff6jyl5  thm-s0001-iamfoo  replicated  1/1       devmtl/iam-this-ctn:1.0.1-alpine-0
o8p4q85axkwy  thm-s0002-iambar  replicated  1/1       devmtl/iam-this-ctn:1.0.1-alpine-0
wedrfqzkg3zp  thm-s0003-caply   replicated  1/1       devmtl/nginx-fire:1.10.3-alpine-0
ql9yapc0brnk  thm-s0003-valgo   replicated  1/1       devmtl/caddy:0.9.5-alpine-0
vu3jhyo71oos  traefik           replicated  1/1       traefik:v1.1.2-alpine

or this using 2 commands:

root@N01-par1-dev-e:~/deploy-setup# echo; \
> docker service ls | head -n 1; \
> docker service ls | tail -n +2 |  sort -k2,2 -k1; echo;

ID            NAME              MODE        REPLICAS  IMAGE
yru8n6zxmp08  consul            global      4/4       consul:latest
1lb98n83fttr  mysql             replicated  1/1       devmtl/percona-fire:5.7.16-10-1
i75t4zef8x8c  papertrail        global      4/4       gliderlabs/logspout:latest
4s14t7f13fp8  portainer         replicated  1/1       portainer/portainer:1.11.3
8wojufyq3dwn  resilio           global      4/4       devmtl/resilio-fire:2.4.4-alpine-0
vn8fhhfvb6pw  sematext          global      4/4       sematext/sematext-agent-docker:1.31.11
mwxtlff6jyl5  thm-s0001-iamfoo  replicated  1/1       devmtl/iam-this-ctn:1.0.1-alpine-0
o8p4q85axkwy  thm-s0002-iambar  replicated  1/1       devmtl/iam-this-ctn:1.0.1-alpine-0
wedrfqzkg3zp  thm-s0003-caply   replicated  1/1       devmtl/nginx-fire:1.10.3-alpine-0
ql9yapc0brnk  thm-s0003-valgo   replicated  1/1       devmtl/caddy:0.9.5-alpine-0
vu3jhyo71oos  traefik           replicated  1/1       traefik:v1.1.2-alpine

Thanks in advance!

回答1:

You can use awk to extract the name from the NAME column and sort the array of names generated to print the lines according to this order :

For docker service ls, the position of names and mode is stored to substring the name. Then the sort of the key array (containing names) is processed with asort :

docker service ls | awk ' 
{
    if (NR == 1) {
        print $0
        names=index($0,"NAME")
        mode=index($0,"MODE")
    }
    else{
        key[NR-2]=substr($0,names,mode-1-names) "\t" NR
        value[NR-2]=$0
    }
}
END {
    asort(key)
    for (i=1; i<=(NR-1); i++) {
        split(key[i],a,"\t")
        print value[a[2]-2]
    }
}'

The result is printed according to the order of sorted key array which contains the couple [name]\t[index]. The index is used to get the line to be printed.

In the case of docker ps -a, NAMES is the last column so we take a fixed value for the length here 100 :

docker ps -a | awk ' 
{
    if (NR == 1) {
        print $0
        names=index($0,"NAME")
    }
    else{
        key[NR-2]=substr($0, names, 100) "\t" NR
        value[NR-2]=$0
    }
}
END {
    asort(key)
    for (i=1; i<=(NR-1); i++) {
        split(key[i],a,"\t")
        print value[a[2]-2]
    }
}'

Check this post for another example of asort



标签: bash docker