Search code examples
amazon-web-servicessystemd

Escape correctly long sequence of systemd command


I have the following systemd unit

[Unit]
Description=Tag EBS Volumes without tags with AutoScaling Group tags
[Service]
Type=oneshot
ExecStartPre=/bin/bash -c "/usr/bin/curl -s https://stedolan.github.io/jq/download/linux64/jq > /usr/local/bin/jq && chmod +x /usr/local/bin/jq"
ExecStart=/bin/bash
      -c 'AWS_REGION=$(/usr/bin/curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed 's/[a-z]$//'); \
          INSTANCE_ID=$(/usr/bin/curl -s http://169.254.169.254/latest/meta-data/instance-id); \
          VOLUMES=$(/usr/local/bin/aws ec2 describe-volumes --region $AWS_REGION --filters Name=attachment.instance-id,Values=$INSTANCE_ID | /usr/local/bin/jq -r '"'"'.Volumes[] | select(.Tags == null) | .Attachments[].VolumeId'"'"'); \
          AUTOSCALING_GROUP=$(/usr/local/bin/aws autoscaling describe-auto-scaling-instances --region $AWS_REGION --instance-ids $INSTANCE_ID | /usr/local/bin/jq -r .AutoScalingInstances[].AutoScalingGroupName); \
          TAGS=$(/usr/local/bin/aws autoscaling describe-tags --region $AWS_REGION --filters Name=auto-scaling-group,Values=$AUTOSCALINGGROUP --query '"'"'Tags[*].{Key:Key,Value:Value}'"'"'); \
          /usr/local/bin/aws ec2 create-tags --region "$AWS_REGION" --resources "$VOLUMES" --tags "$TAGS";'

I'd like to ask if you have some recommendations to make it more readable and working. I'm not able to escape correctly the sequence and I get error to execute it.

Dec 16 09:43:36 ip-172-20-39-162 systemd[1]: Started Tag EBS Volumes without tags with AutoScaling Group tags.
Dec 16 10:21:03 ip-172-20-39-162 systemd[1]: [/lib/systemd/system/kops-hook-tag-ebs-volumes.service:11] Unknown lvalue '-c 'AWS_REGION' in section 'Service'

Solution

  • Looking purely at your question, you're missing an escape \ on line

    ExecStart=/bin/bash
    

    Should be

    ExecStart=/bin/bash \
     -c 'AWS_REGION=$(/usr/bin/curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed 's/[a-z]$//'); \
              INSTANCE_ID=$(/usr/bin/curl -s http://169.254.169.254/latest/meta-data/instance-id); \
              VOLUMES=$(/usr/local/bin/aws ec2 describe-volumes --region $AWS_REGION --filters Name=attachment.instance-id,Values=$INSTANCE_ID | /usr/local/bin/jq -r '"'"'.Volumes[] | select(.Tags == null) | .Attachments[].VolumeId'"'"'); \
              AUTOSCALING_GROUP=$(/usr/local/bin/aws autoscaling describe-auto-scaling-instances --region $AWS_REGION --instance-ids $INSTANCE_ID | /usr/local/bin/jq -r .AutoScalingInstances[].AutoScalingGroupName); \
              TAGS=$(/usr/local/bin/aws autoscaling describe-tags --region $AWS_REGION --filters Name=auto-scaling-group,Values=$AUTOSCALINGGROUP --query '"'"'Tags[*].{Key:Key,Value:Value}'"'"'); \
              /usr/local/bin/aws ec2 create-tags --region "$AWS_REGION" --resources "$VOLUMES" --tags "$TAGS";'
    

    To simplify things; I would suggest setting your environment variables in ExecStartPre