0

I am running a shell script to run awk command on a remote host. The awk command runs fine locally, but when run for the remote host fails (the redirected file is empty):

Here is the script run on remote host:

host=160.110.235.30
IFM_MOUNT=/opt/insiteone/fuse-mount1
ssh -T root@$host << 'EOF'
awk -v p="$IFM_MOUNT" '{a[NR]=$0}{if(match($0,p)>0){for(i=NR-2;i<=NR+7;i++)d[i]=1}}END{for(i=1;i<=NR;i++)if(!d[i])print a[i]} ' smb.conf >> smb.conf.tmp
EOF

smb.conf.tmp is empty in remote host !!

Locally:

cat smb.conf
[DCCAArchive]
        comment = DCCA Archive File System
        path = /opt/insiteone/fuse-mount/ifm
        read only = No
        case sensitive = yes
        public = yes
        case sensitive = yes
        writeable = yes
        create mask=0777
        guest ok = Yes


[DCCAArchive1]
        comment = DCCA Archive File System
        path = /opt/insiteone/fuse-mount1/ifm
        read only = No
        case sensitive = yes
        public = yes
        case sensitive = yes
        writeable = yes
        create mask=0777
        guest ok = Yes

Running awk locally from shell:
IFM_MOUNT=/opt/insiteone/fuse-mount1
awk -v p="$IFM_MOUNT" '{a[NR]=$0}{if(match($0,p)>0){for(i=NR-2;i<=NR+7;i++)d[i]=1}}END{for(i=1;i<=NR;i++)if(!d[i])print a[i]} ' smb.conf >> smb.conf.tmp

Output (deletes the line matching IFM_MOUNT):
[DCCAArchive]
        comment = DCCA Archive File System
        path = /opt/insiteone/fuse-mount/ifm
        read only = No
        case sensitive = yes
        public = yes
        case sensitive = yes
        writeable = yes
        create mask=0777
        guest ok = Yes

I followed this link for awk running on remote host

Community
  • 1
  • 1
RajSanpui
  • 11,556
  • 32
  • 79
  • 146
  • One thing I notice - that link shows `-t` with ssh while you're showing `-T`. – n0741337 Jun 23 '15 at 16:19
  • @n0741337: That is for suppressing the error for Pseudo terminal allocation – RajSanpui Jun 23 '15 at 16:21
  • Okay, seems like it is working if instead of `$IFM_MOUNT` i hardcode the path. But why? – RajSanpui Jun 23 '15 at 16:50
  • Because within the single-quoted here document, the variable `IFM_MOUNT` is unset. The single quotes inhibit any variable interpolation and the remote shell obviously has no idea what variables your local shell has defined. – tripleee Jun 23 '15 at 16:54
  • @tripleee: Sorry, can you please tell me what is the correct way? I need to use the here doc i thought. – RajSanpui Jun 23 '15 at 16:55
  • Posted an actual answer. A here document is definitely not mandatory here; it's just one among many possible quoting mechanisms, and often not a good choice for `ssh`. – tripleee Jun 23 '15 at 17:03

1 Answers1

3

The quoting mechanism you have chosen prevents the remote shell from seeing the locally defined variable IFM_MOUNT. Use double quotes instead to have the value interpolated into the string.

host=160.110.235.30
IFM_MOUNT=/opt/insiteone/fuse-mount1
ssh root@$host "awk -v p='$IFM_MOUNT' '
    {a[NR]=\$0}
    {if(match(\$0,p)>0)
      for(i=NR-2;i<=NR+7;i++)
          d[i]=1}
    END{
      for(i=1;i<=NR;i++)if(!d[i])print a[i]} ' smb.conf >> smb.conf.tmp"

Notice how single quotes inside double quotes do not actually quote anything; and so any literal dollar sign needs to be escaped with a backslash.

(I was tempted to make a more substantial refactoring of your Awk script, but that would perhaps obscure the point.)

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Thanks. That really helped. – RajSanpui Jun 23 '15 at 17:07
  • I need to rename the file remotely as well from smb.conf.tmp back to smb.conf, a here doc would have helped me to avoid asking the password to the user multiple times, by clubbing multiple commands inside same here doc. Do we have any other way for that please? – RajSanpui Jun 23 '15 at 17:21
  • 1
    Just put multiple commands in the string. `ssh remote "awk 'this'; cat 'that'; echo 'done'"` – tripleee Jun 23 '15 at 17:46