Unverified Commit c0385c57 authored by liuzhe-lz's avatar liuzhe-lz Committed by GitHub
Browse files

Escape environment variable PATH for Windows scripts (#3898)

parent f9512aa5
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
'use strict';
// for readability
const singleQuote = "'";
const doubleQuote = '"';
const backtick = '`';
const backslash = '\\';
const doubleBacktick = '``';
const doubleBackslash = '\\\\';
const newline = '\n';
/**
* Convert a string into quoted and escaped string for shell script.
* This function supports multi-line strings as well.
*
* Examples:
* hello --> 'hello'
* C:\Program Files\$app --> 'C:\Program Files\$app'
* a'b"c$d<ENTER>e\f`g --> $'a\'b"c$d\ne\\f`g' (Linux & macOS)
* a'b"c$d<ENTER>e\f`g --> "a'b`"c`$d`ne\f``g" (Windows)
**/
export function shellString(str: string): string {
return process.platform === 'win32' ? powershellString(str) : bashString(str);
}
/**
* Convert a string into quoted and escaped string for bash script. It supports multi-line strings.
**/
export function bashString(str: string): string {
// for readability of generated script,
// use ansi-c quoting when `str` contains single quote or newline,
// use single quotes otherwise
if (str.includes(singleQuote) || str.includes(newline)) {
str = str.replaceAll(backslash, doubleBackslash);
str = str.replaceAll(singleQuote, backslash + singleQuote);
str = str.replaceAll(newline, backslash + 'n');
return '$' + singleQuote + str + singleQuote;
} else {
return singleQuote + str + singleQuote;
}
}
/**
* Convert a string into quoted and escaped string for PowerShell script. It supports multi-line strings.
**/
export function powershellString(str: string): string {
// for readability and robustness of generated script,
// use double quotes for multi-line string,
// use single quotes otherwise
if (str.includes(newline)) {
str = str.replaceAll(backtick, doubleBacktick);
str = str.replaceAll(doubleQuote, backtick + doubleQuote);
str = str.replaceAll(newline, backtick + 'n');
str = str.replaceAll('$', backtick + '$');
return doubleQuote + str + doubleQuote;
} else {
str = str.replaceAll(singleQuote, singleQuote + singleQuote);
return singleQuote + str + singleQuote;
}
}
......@@ -11,6 +11,7 @@ import * as tkill from 'tree-kill';
import { NNIError, NNIErrorNames } from '../../common/errors';
import { getExperimentId } from '../../common/experimentStartupInfo';
import { getLogger, Logger } from '../../common/log';
import { powershellString } from '../../common/shellUtils';
import {
HyperParameters, TrainingService, TrialJobApplicationForm,
TrialJobDetail, TrialJobMetric, TrialJobStatus
......@@ -446,7 +447,7 @@ class LocalTrainingService implements TrainingService {
if (process.platform !== 'win32') {
runScriptContent.push('#!/bin/bash');
} else {
runScriptContent.push(`$env:PATH="${process.env.path}"`)
runScriptContent.push(`$env:PATH=${powershellString(process.env.path!)}`)
}
for (const variable of variables) {
runScriptContent.push(setEnvironmentVariable(variable));
......
......@@ -10,6 +10,7 @@ import * as component from '../../../common/component';
import { getLogger, Logger } from '../../../common/log';
import { ExperimentConfig } from '../../../common/experimentConfig';
import { ExperimentStartupInfo } from '../../../common/experimentStartupInfo';
import { powershellString } from '../../../common/shellUtils';
import { EnvironmentInformation, EnvironmentService } from '../environment';
import { isAlive, getNewLine } from '../../../common/utils';
import { execMkdir, runScript, getScriptName, execCopydir } from '../../common/util';
......@@ -80,7 +81,7 @@ export class LocalEnvironmentService extends EnvironmentService {
private getScript(environment: EnvironmentInformation): string[] {
const script: string[] = [];
if (process.platform === 'win32') {
script.push(`$env:PATH="${process.env.path}"`)
script.push(`$env:PATH=${powershellString(process.env.path!)}`)
script.push(`cd $env:${this.experimentRootDir}`);
script.push(`New-Item -ItemType "directory" -Path ${path.join(this.experimentRootDir, 'envs', environment.id)} -Force`);
script.push(`cd envs\\${environment.id}`);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment