简体   繁体   中英

Function calls in Here Document for unix shell script

I'm working on a shell script to move some files around. This script needs to be able to operate on files either on a local machine or on a remote server depending on the arguments passed in. I have managed to put together a simple function that does what I want. What I can't seem to figure out is how to use that function in a Here document so it can be executed on the remote server. I found a similar question here: From shell script can we invoke function from here document but the given answers don't work for me.

Here is what I have come up with so far:

myscript.sh

REMOTE_HOST=myserver
JETTY_BASE=/opt/web/jetty

doMove()
{
    echo "$JETTY_BASE/webapps/eyerep-data/$1"       
    sudo touch $JETTY_BASE/webapps/eyerep-data/$1/myfile
    ls $JETTY_BASE/webapps/eyerep-data/$1;
}

moveRemote()
{
    echo "attempting move with here doc"    
    ssh -t $REMOTE_HOST "/bin/bash <<EOF
$(doMove $1) 
EOF"
    
}

moveFiles()
{   
        case "$1" in
      # remote deploy
      remote)
        moveRemote $2
        ;;
      # local deploy
      local)
        doMove $2
        ;;
      *)
        echo "Usage: myscript.sh {local|remote}"
        exit 1
        ;;
    esac
    
}

If I run the above with

./myscript.sh remote dev

I get an output like:

attempting move with here doc
/bin/bash: line 1: /opt/web/jetty/webapps/eyerep-data/: Is a directory
/bin/bash: line 2: dev: command not found
/bin/bash: line 3: eyerep-data-dev.xml: command not found
/bin/bash: line 4: eyerep-data-local.xml: command not found
/bin/bash: line 5: local: can only be used in a function

Looking at the output, it looks like it is trying to pass the output from the 'echo' and 'ls' calls to /bin/bash as commands instead of printing them to the console. While this is a contrived example, I would like to be able to have logging statements inside my function that print to stdout. What is the best way to deal with this?

Try this one:

#!/bin/bash

REMOTE_HOST=myserver
JETTY_BASE=/opt/web/jetty

generateMoveCommands() {
    __="echo ${JETTY_BASE@Q}/webapps/eyerep-data/${1@Q}
sudo touch ${JETTY_BASE@Q}/webapps/eyerep-data/${1@Q}/myfile
ls ${JETTY_BASE@Q}/webapps/eyerep-data/${1@Q}"
}

moveLocal() {
    generateMoveCommands "$1"
    eval "$__"
}

moveRemote() {
    echo "Attempting move with here doc"
    generateMoveCommands "$1"
    printf '%s\n' "$__" | ssh -t "$REMOTE_HOST" /bin/bash
}

showUsage() {
    echo "Usage: $0 {local|remote} file"
    exit 1
}

main() {
    case $1 in
    # remote deploy
    remote)
        [[ $2 ]] || showUsage
        moveRemote "$2"
        ;;
    # local deploy
    local)
        [[ $2 ]] || showUsage
        moveLocal "$2"
        ;;
    *)
        showUsage
        ;;
    esac
}

main "$@"

The form ${param@Q} expands value to a quoted version which allows to be safely re-evaluated as an argument. It's a Bash feature that became available starting 4.4.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM