Using shell script in node

Time:2021-1-13

background

In development, we may need some scripts to batch process our business logic in specific situations. How to call shell scripts in nodejs?

newly build

  1. Create a new script file under the project

    touch newFile.sh

  2. Modify file permissions

    chmod 777 newFile.sh Modify the file to be readable, writable and executable

Nodejs call

File reading

//Using the file reading method in the child process of nodejs

const { execFile } = require(‘child_process’);

Examples

DocsService.publishAllDocs = (req, res) => {
  req.session.touch();
  const { docName, pathName, saveDocsList, docType } = req.body;
  var docText = req.body.docText;
  var newGit = req.body.newGit;
  //Get file path
  var filepath = path.join(__dirname, '../../bin/rnsource/publishAllDocs.sh');
  var fileArr, fileName, spath, dirnameBack, docbackList = [], docbackPath, docPath = "";
  var username = req.session.user_name;
  var str = docName+'/'+ pathName + '|'+ username;
  var reg = new RegExp(`^(${str})`);
  saveDocsList.map((item, index)=>{
      fileArr = item.pathName.split("/");
      fileName = fileArr[fileArr.length-1];
      if(docType == "docsify"){
          dirnameBack = fileName != "" ? `../../gitlib/docBackup/${docName}/docs/${item.pathName}`:`../../gitlib/docBackup/${docName}/docs/README.md`
      }else{
          spath = item.pathName.split(fileName)[0];
          dirnameBack = spath != "" ?'../../gitlib/docBackup/'+ docName+'/'+ spath +'/'+fileName:'../../gitlib/docBackup/'+ docName+'/' + fileName;  
      }

      docbackPath = path.join(__dirname, dirnameBack);
      docbackList.push(docbackPath);
      docPath +=  docbackPath + " ";
  })
  docPath += ""
  //CWD sets the current path. What I set here is the current location of nodejs code
  execFile(filepath, [docName, docPath, docType], { cwd: '.' }, function(err, stdout, stderr){
      logger.info(stdout);
      if(err){
          loggerFileError({ user:username , docName:docName , pathname: 'all', operate: "gitbook file one click publishing", err});
          res.json({
              respCode: -1,
              Errmsg: "one click publish failed"
          })
      }else{
          res.json({
              respCode: 0,
              MSG: "one click publishing succeeded"
          })
          gitPush({ docName, fileName, docbackPath: docbackList, username, pathName, docType })
          unblockFile({ docName, username, pathName, reg });
      }
  }) 
}

Callback

Successful execution will return the command executed by the script

Using shell script in node

execFile

  • The first parameter: the external program to call, here is the file to read
  • The second parameter: the parameter passed to the external program (must be placed in the array)
  • The third parameter: callback function, in which the execution result of external program can be returned

shell

publishAllDocs.sh Idea: all the scripts described here are shell scripts not in windows. Bat scripts in windows are not explained here

#$1 document outermost directory $2 currently modified file name $3 currently modified file directory
cd $(pwd)/gitlib/docs/$1
echo "come in"
for item in $2; do
    echo "${item}"
    cp -f ${item} ${item/docBackup/docs}
done
#Echo "initialization entry"
echo "$(pwd)/gitlib/docs/$1"
if [ "$3" == "docsify" ];then
    #Copy the files in the specified directory, such as $1 / $3 / $2 docs / CST / 7e4ce1de04621e0b/
    #Such as CP - RF.. /. / DocBackup / wireless / docs / CST / 7e4ce1de04621e0b / 10708d589 eedfffd.md  ./docs/cst/7e4ce1de04621e0b/
    cp -rf ./docs ../../../public/docs/$1
else
    #Handling gitbook type documents
    gitbook build
    Echo "copy document"
    cp -rf ./_book/* ../../../public/docs/$1
fi

Parameter receiving

  • The parameters are obtained according to the data transferred during business call
  • Directly use “$” to get
  • The order of data acquisition is the order of data transmission
  • Remember that it’s not the value of the array corner, and the first parameter of the array is $1

The use of for loop

  • Using the form for… In in shell
  • Example of loop body data requiring loop

    "/Users/Desktop/work/docManager/docServer/gitlib/docBackup/mygitbook/docs/d09985fc67088b35/d09985fc67088b35.md /Users/Desktop/work/docManager/docServer/gitlib/docBackup/mygitbook/docs/d09985fc67088b35/d09985fc67088b35/6f7a2c61c9bac0a3.md /Users/Desktop/work/docManager/docServer/gitlib/docBackup/mygitbook/README.md /Users/Desktop/work/docManager/docServer/gitlib/docBackup/mygitbook/docs/d09985fc67088b35/d09985fc67088b35/6f7a2c61c9bac0a3.md "
  • The data of the loop body in the shell script is special, not our regular array or JSON
  • Directly is a string separated by spaces, such as: “a B C D E”
##$2 is the data that is spliced according to the format of the service parameters received in the script, as shown in the above data example
##Loop for... In remember that you must add do to execute the loop body and use done to end the loop
##Each subitem of the item loop body, such as: users / desktop / work / docmanager / docserver / gitlib / DocBackup / mygitbook / docs / d09985fc67088b35 / d09985fc67088b35.md
for item in $2; do
    echo "${item}"
    cp -f ${item} ${item/docBackup/docs}
done
##${item / DocBackup / docs} string replacement
##Here, replace DocBackup in the item path with docs. For a detailed explanation, please see the following shell string replacement

Shell specifies string substitution

In JS, we can use replace to replace strings. How to implement the change in shell?

Example:

string “abc12342341”

  • Echo ${string / 23 / BB} / / abc1bb42341 replace once
  • Echo ${string / / 23 / BB} / / abc1bb4bb41 double slashes replace all matches
  • Echo ${string / # ABC / BB} / / bb12342341 # start with what to match, the ^ in root PHP is a bit like
  • echo ${string/%41/bb}//What does abc123423bb% end with? The $in root PHP is a bit like that

The use of if condition judgment

grammar

if[];then
    ...
else
    ...
fi

Examples

##Conditional judgment is to use [] instead of ()
##Add after;
if [ "$3" == "docsify" ];then
    #Copy the files in the specified directory, such as $1 / $3 / $2 docs / CST / 7e4ce1de04621e0b/
    #Such as CP - RF.. /. / DocBackup / wireless / docs / CST / 7e4ce1de04621e0b / 10708d589 eedfffd.md  ./docs/cst/7e4ce1de04621e0b/
    cp -rf ./docs ../../../public/docs/$1
else
    #Handling gitbook type documents
    gitbook build
    Echo "copy document"
    cp -rf ./_book/* ../../../public/docs/$1
fi

be careful

  • “Double quotation marks” should be used for string in condition judgment
  • If there is a variable (string) in the condition judgment, the variable should also be added with “” double quotation marks
  • Conditional judgment should be added after, and then should be used to continue execution
  • Fi should be used at the end of conditional judgment