Using variables in the SCP command in QSHELL.

Any IBM i topic that does not fit in another forum
Post Reply
fisherman
Posts: 4
Joined: Tue Nov 28, 2023 11:33 am

Using variables in the SCP command in QSHELL.

Post by fisherman »

Hello Scott,

I have been using your AS400 documentation for many years. First of all, a big thank you from Germany.

Now to my problem. I want to transfer data to an external server via SCP command. This works if I enter the SCP command fixed in the script, as soon as I want to control the transfer by variable, I get error 127 and the command fails.

Working script without variables:

Code: Select all

#!/bin/sh                                                                                             
export DISPLAY= SSH_ASKPASS=/QOpenSys/etc/openssh_password_scp_script.sh                              
printf | scp -P 2231 /home/Shop/wf/SFTP00_TST.txt bhk_wawi@OXIDADMIN.BASLER-BEAUTY.DE:/data/data/wawi/...........
--> Result: The result only contains the password if the transfer is correct.
password

Not working with variable:

Code: Select all

 #!/bin/sh                                                               
 export DISPLAY= SSH_ASKPASS=/QOpenSys/etc/openssh_password_scp_script.sh
 printf | "${SSH_CMD}"                                                   
 echo $?
 

Code: Select all

--> Result:
password/home/scpuser/V0_batch_scp_script_mit_Parameter.sh[3]:  scp -P 2231 /home/Shop/wf/SCP00_TST.txt bhk_wawi@OXIDADMINN.BASLER-BEAUTY.DE:/data/data/wawi/........
127
Commands from the CL program

Code: Select all

CHGVAR     VAR(&AS400VERZ)  VALUE('/home/Shop/wf/')                
CHGVAR     VAR(&AS400FILE)   VALUE('SCP00_TST.txt')                                                                    
CHGVAR     VAR(&OXIDUSER)   VALUE('bhk_wawi')                      
CHGVAR     VAR(&OXIDSERVER) VALUE('OXIDADMIN.BASLER-BEAUTY.DE')    
CHGVAR     VAR(&OXIDVERZ)   VALUE('/data/data/wawi/Basler2Shop/customerDE/backup/wf/file.txt')                                                                   
CHGVAR     VAR(&SCP_CMD)    VALUE(' scp -P 2231' *BCAT +           
                                   &AS400VERZ     *TCAT +          
                                   &AS400FILE     *TCAT ' ' *CAT + 
                                   &OXIDUSER      *TCAT '@' *CAT + 
                                   &OXIDSERVER    *TCAT ':' *CAT + 
                                   &OXIDVERZ)                      
ADDENVVAR  ENVVAR(SSH_CMD) VALUE(&SCP_CMD) REPLACE(*YES) 
QSH        +                                             
             CMD('/QOpenSys/etc/openssh_password_scp_script.sh')   
QSH        CMD('exec /QOpenSys/usr/bin/ksh -c +           
             "/home/scpuser/V0_batch_scp_script_mit_Parameter.sh"')     
It would be nice if I could be given the right tip here in the forum.

Best regards
Wolfgang
Scott Klement
Site Admin
Posts: 658
Joined: Sun Jul 04, 2021 5:12 am

Re: Using variables in the SCP command in QSHELL.

Post by Scott Klement »

Whenever you post data containing code, please put [code] before the first line of code, and [/code] after the last line. This saves me a lot of time and frustration trying to understand your code.

Also, I've never written documentation for the AS400. When I started doing that sort of work, I wrote for the iSeries. After that I wrote for the System i. And then for the past 15 years, for the IBM i. Although I worked on the AS/400, I did not write public facing documentation back then.
Scott Klement
Site Admin
Posts: 658
Joined: Sun Jul 04, 2021 5:12 am

Re: Using variables in the SCP command in QSHELL.

Post by Scott Klement »

I've spent a lot of time editing your post to add the [code] tags, as well as time trying to figure out what you're asking. Sadly, I do not have unlimited time, so I will just ask some questions and then I need to work on other things.
  • Why does your script print the password on the screen? That seems like a very bad idea. But, from your description, it seems that this is your goal? Why would it be your goal?!
  • The DISPLAY variable is normally used by the X11 window system. Are you using that? I'm confused as to why you are blanking it out.
  • What problem are you having? Are there error messages? (Note: 127 is not an error message -- it is the exit status.) What is not working? You just want it to print the password on the screen, that's all that matters to you?
  • What is in the SSH_CMD variable at the time that you run the V0_batch_scp_script_mit_Parameter.sh script? Have you displayed it in debug, or in WRKENVVAR?
fisherman
Posts: 4
Joined: Tue Nov 28, 2023 11:33 am

Re: Using variables in the SCP command in QSHELL.

Post by fisherman »

Hello Scott,

Firstly, thank you for replying so quickly. I looked at all my documentation - very helpful - from you and it says IBM i everywhere and not AS400. I must apologise for that. Also for my confusing enquiry, which you kindly put into a much more readable format.

Viele Grüße
Wolfgang
fisherman
Posts: 4
Joined: Tue Nov 28, 2023 11:33 am

Re: Using variables in the SCP command in QSHELL.

Post by fisherman »

In my second post, I now try to make the whole thing easier to read:

I would like to transfer data from our IBMi to another system using the SecureCopy command with variable path and file names. I have created a CL programme for this purpose. The variable that I transfer from the CLP to the shell script is currently entered permanently in the programme during the test phase. I then add the environment variables and call the shell script "V0_batch_scp_script_with_parameters.sh" using the "QSH" command.

IFS:

Code: Select all

Verzeichnis  . . . :   /home/Shop/wf 
      SCP00_TST.txt         STMF     
      SCP01_TST.txt         STMF


Commands from the CL program: QCLSRC/SCP00_TST:

Code: Select all

DCL           VAR(&SCP_CMD) TYPE(*CHAR) LEN(256)
CHGVAR     VAR(&SCP_CMD) VALUE('scp -P 2231 +             
                                                    /home/Shop/wf/SCP00_TST.txt +                
                                                    bhk_wawi@OXIDADMIN.BASLER-BEAUTY.DE:/data/d+ 
                                                    ata/wawi/Basler2Shop/customerDE/backup/wf/') 
ADDENVVAR  ENVVAR(QIBM_QSH_CMD_ESCAPE_MSG) VALUE(Y) REPLACE(*YES)
ADDENVVAR  ENVVAR(QIBM_QSH_CMD_OUTPUT) +                  
                   VALUE('FILEAPPEND=/home/scpuser/SCP00_TST_Logfile.txt') REPLACE(*YES)
ADDENVVAR  ENVVAR(SSH_CMD) VALUE(&SCP_CMD) REPLACE(*YES) 
QSH            CMD('exec /QOpenSys/usr/bin/ksh -c +                    
                        "/home/scpuser/V0_batch_scp_script_mit_Parameter.sh"')  
Line 3 of the shell script contains the assignment to the CLP variable. Line 5 of the shell script contains the SCP command using the CLP variable. In line 7 of the shell script, I have entered the command manually in the shell script.

Shell-Script: /home/scpuser/V0_batch_scp_script_mit_Parameter.sh:

Code: Select all

    ***************Datenanfang*****************                                                                             
1   #!/bin/sh                                                                                                                
2   export DISPLAY= SSH_ASKPASS=/QOpenSys/etc/openssh_password_scp_script.sh                                                 
3   mycommand="${SSH_CMD}"                                                                                                   
4   mycommand=${mycommand}                                                                                                   
5   printf | "${mycommand}"                                                                                                  
6   echo $?                                                                                                                  
7   printf | scp -P 2231 /home/Shop/wf/SCP01_TST.txt bhk_wawi@OXIDADMIN.BASLER-BEAUTY.DE:/data/data/wawi/Basler2Shop/customerDE               /backup/wf/
8   echo $?                                                                                                                  
    ***************Datenende******************* 

The problem is: Line 5 in the shell script with the variable "mycommand" does not work and ends with the status message "127". The manually entered line 7 in the shell script works, the file is transferred to the external system and ends with the status message "0". But I need the version with variables.

Log-File: /home/scpuser/SCP00_TST_Logfile.txt:

Code: Select all

 ***************Datenanfang*****************                                                                                       
/home/scpuser/V0_batch_scp_script_mit_Parameter.sh[5]: scp -P 2231 /home/Shop/wf/SCP00_TST.txt bhk_wawi@OXIDADMIN.BASLER-BEAUTY.DE:/data/data/wawi/Basler2Shop/customerDE/backup/wf/:  nicht gefunden. 
127                                                                                                                                
0                                                                                                                                  
 ***************Datenende*******************   
 


best regards
Wolfgang
Scott Klement
Site Admin
Posts: 658
Joined: Sun Jul 04, 2021 5:12 am

Re: Using variables in the SCP command in QSHELL.

Post by Scott Klement »

Let me explain some basics, first:

A command starts with a program name, followed by parameters separated by spaces. For example:

Code: Select all

myProgram parameter1 parameter2
In this example, the program name is myProgram, and it's being passed two parameters, both character strings containing parameter1 and parameter2. A more "real" example might look like this:

Code: Select all

scp scott@mysystem:/tmp/myfile.txt thisfile.txt
In this example, the program is 'scp', and the first parameter is 'scott@mysystem:/tmp/myfile.txt' (yes, that's all one parameter because there are no spaces), the second parameter is 'thisfile.txt'.

What if you wanted to have spaces inside of a parameter? for example:

Code: Select all

scp my file name.txt scott@remotesystem:
This would be a problem, because the first parameter should be 'my file name.txt', all one parameter -- but it won't work because spaces separate multiple parameters. So it will think you are providing 3 different file names, 'my', 'file', and 'name.txt' instead of one filename with spaces in it. To solve that, you need to put it in quotes.

Code: Select all

scp "my file name.txt" scott@remotesystem:
The quotes allow multiple pieces to be treated as a single parameter.

Here's what you are doing:

Let's take your original script (without all the unnecessary 'mycommand' stuff that you added, since the 'mycommand' only makes it more difficult without providing any additional value)

Code: Select all

printf | "${SSH_CMD}"
So if SSH_CMD is the command that works. Why are you putting quotes around it?

A simple scp command may look like this:

Code: Select all

scp file1 file2
As we learned above, this is a program name 'scp', and two parameters 'file1' and 'file2'. But what if you added quotes to it?

Code: Select all

"scp file1 file2"
Remember, quotes prevent the spaces from separating out the parameters. So now the ONLY thing you have is the program name. And the program name is 'scp file1 file2', the whole string is the program name -- including the spaces, including the words file1 and file2, they're all part of the program name because it's all in quotes, and therefore all part of one element of the command line.

The result with the quotes will be:

Code: Select all

/path/to/scriptname.sh: scp file1 file2: not found                                                                                                   
Or "nicht gefunden" in German. Because it can't find a program named 'scp file1 file2' (with the spaces in the name) in your PATH. And that makes perfect sense, in this case you obviously didn't mean to have quotes around the whole string.

In your case maybe it's harder to see since you're doing it like this (simplified)

Code: Select all

ADDENVVAR ENVVAR(SSH_CMD) VALUE('scp file1 file2')
QSH CMD('/path/to/myscript.sh')

Code: Select all

#!/bin/sh
printf | "${SSH_CMD}"
Replace ${SSH_CMD} with the contents of the variable, then the script looks like this:

Code: Select all

#!/bin/sh
printf | "scp file1 file2"
Do you see the problem? There should not be quoted around the scp command string.

Instead you want to do it without the quotes

Code: Select all

#!/usr/bin/env sh
export DISPLAY= SSH_ASKPASS=/QOpenSys/etc/openssh_password_scp_script.sh                
printf | ${SSH_CMD}
exit $?
Notice that:
  • I removed the quotes.
  • I replaced the bang path with one that does not require sh to be in the /bin directory. I did that because there is no /bin/sh on IBMi -- so I don't know why you hard coded that location. I suspect you copied this from a Unix/Linux example, and didn't adjust it for IBM i.
  • instead of printing the exit status, I copied it to be the exit status of the script. This will allow you to check it from the CL program.
The CL program could be rewritten to work better as well, but I don't have time to do that right now.
fisherman
Posts: 4
Joined: Tue Nov 28, 2023 11:33 am

Re: Using variables in the SCP command in QSHELL.

Post by fisherman »

Hallo Scott,
thank you very much for your help. The SCP now works perfectly. I had a general problem understanding how to use quotes in a script. So thank you again for your detailed instructions. I am now using your script exactly as you posted it and I have removed all unnecessary quotes in my CLP.

I have one small final question, see code in part 2: I query the MSGID and the EXIT-STATUS in the CLP via RCVMSG. Is that OK, or should I query the exit status differently? it works.

Code Part 1, for information only. Set Variabale, execute QSH and check for Escape-MSG.

Code: Select all

ADDENVVAR  ENVVAR(QIBM_QSH_CMD_ESCAPE_MSG) VALUE(Y) +              
             REPLACE(*YES)                                         
ADDENVVAR  ENVVAR(QIBM_QSH_CMD_OUTPUT) +                           
             VALUE('FILEAPPEND=/home/scpuser/SCP00_TST+            
             _Logfile.txt') REPLACE(*YES)                          
ADDENVVAR  ENVVAR(SSH_CMD) VALUE(&SCP_CMD) REPLACE(*YES)           
                                                                   
QSH        CMD('exec /QOpenSys/usr/bin/ksh -c +                    
             "/home/scpuser/V0_batch_scp_script_mit_Parameter.sh"')

MONMSG     MSGID(QSH0005 QSH0006 QSH0007) EXEC(DO) /* +     
             Fehler bei Übertragung der Datei an +          
             externen Server. */  
RCVMSG     MSGTYPE(*LAST) RMV(*YES) MSGDTA(&MSGDTA) +       
             MSGID(&MSGID)                                  
CHGVAR     VAR(&RESULT)  VALUE(%SST(&MSGDTA 1 4))           
CHGVAR     VAR(&STATUS)  VALUE(%BIN(&RESULT))               
CHGVAR     VAR(&STATUSA) VALUE(%BIN(&RESULT))               
SNDMSG     MSG(&MSGID *BCAT 'SCP fehlgeschlagen und mit +   
             Status ' *CAT &STATUSA *CAT ' beendet. +       
             Bitte in Verzeichnis "/home/scpuser" die +     
             Logfile "SCP00_TST_Logfile.txt" prüfen.') +    
             TOUSR(FISCHER)                                 
GOTO       CMDLBL(ENDEPGM) /* Programm wird aufgrund +      
             Abbruchnachricht beendet und springt zur +     
             Anzeige der Logfile. */                        
ENDDO
 


Code Part 2. RCVMSG, check MSGID and EXIT-Status.

Code: Select all

RCVMSG     MSGTYPE(*LAST) RMV(*YES) MSGDTA(&MSGDTA) +    
             MSGID(&MSGID) /* Prüfen MSGID und Status. */
CHGVAR     VAR(&RESULT)  VALUE(%SST(&MSGDTA 1 4))        
CHGVAR     VAR(&STATUS)  VALUE(%BIN(&RESULT)) 
SELECT                                                    
WHEN       COND(&MSGID *EQ 'QSH0005' *AND &STATUS *EQ 0) +
             THEN(SNDMSG MSG(&MSGID *BCAT 'SCP +          
             erfolgreich mit Status ' *CAT &STATUSA +     
             *CAT ' beendet.') TOUSR(FISCHER))            
WHEN       COND(&MSGID *EQ 'QSH0005' *AND &STATUS *GT 0) +
             THEN(SNDMSG MSG(&MSGID *BCAT 'SCP +          
             nicht erfolgreich mit Status ' *CAT +        
             &STATUSA *CAT ' beendet. Bitte in +          
             Verzeichnis "/home/scpuser" die Logfile +    
             "SCP00_TST_Logfile.txt" prüfen.') +          
             TOUSR(FISCHER))                              
OTHERWISE  CMD(SNDMSG MSG(&MSGID *BCAT 'mit Status ' +    
             *CAT &STATUSA *CAT ' unbekannt. Das +        
             Programm muss für diese Meldung angepasst +  
             werden. Bitte in Verzeichnis +      
             "/home/scpuser" die Logfile +       
             "SCP00_TST_Logfile.txt" prüfen.') + 
             TOUSR(FISCHER))                     
ENDSELECT
 


Viele Grüße
Wolfgang
Scott Klement
Site Admin
Posts: 658
Joined: Sun Jul 04, 2021 5:12 am

Re: Using variables in the SCP command in QSHELL.

Post by Scott Klement »

It looks good to me.
Post Reply