process-exec-sync.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. 'use strict'
  2. const fs = require('graceful-fs')
  3. const childProcess = require('child_process')
  4. function startsWith (str, search, pos) {
  5. if (String.prototype.startsWith) {
  6. return str.startsWith(search, pos)
  7. }
  8. return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search
  9. }
  10. function processExecSync (file, args, options) {
  11. var child, error, timeout, tmpdir, command
  12. command = makeCommand(file, args)
  13. /*
  14. this function emulates child_process.execSync for legacy node <= 0.10.x
  15. derived from https://github.com/gvarsanyi/sync-exec/blob/master/js/sync-exec.js
  16. */
  17. options = options || {}
  18. // init timeout
  19. timeout = Date.now() + options.timeout
  20. // init tmpdir
  21. var osTempBase = '/tmp'
  22. var os = determineOS()
  23. osTempBase = '/tmp'
  24. if (process.env.TMP) {
  25. osTempBase = process.env.TMP
  26. }
  27. if (osTempBase[osTempBase.length - 1] !== '/') {
  28. osTempBase += '/'
  29. }
  30. tmpdir = osTempBase + 'processExecSync.' + Date.now() + Math.random()
  31. fs.mkdirSync(tmpdir)
  32. // init command
  33. if (os === 'linux') {
  34. command = '(' + command + ' > ' + tmpdir + '/stdout 2> ' + tmpdir +
  35. '/stderr); echo $? > ' + tmpdir + '/status'
  36. } else {
  37. command = '(' + command + ' > ' + tmpdir + '/stdout 2> ' + tmpdir +
  38. '/stderr) | echo %errorlevel% > ' + tmpdir + '/status | exit'
  39. }
  40. // init child
  41. child = childProcess.exec(command, options)
  42. var maxTry = 100000 // increases the test time by 6 seconds on win-2016-node-0.10
  43. var tryCount = 0
  44. while (tryCount < maxTry) {
  45. try {
  46. var x = fs.readFileSync(tmpdir + '/status')
  47. if (x.toString() === '0') {
  48. break
  49. }
  50. } catch (ignore) {}
  51. tryCount++
  52. if (Date.now() > timeout) {
  53. error = child
  54. break
  55. }
  56. }
  57. ['stdout', 'stderr', 'status'].forEach(function (file) {
  58. child[file] = fs.readFileSync(tmpdir + '/' + file, options.encoding)
  59. setTimeout(unlinkFile, 500, tmpdir + '/' + file)
  60. })
  61. child.status = Number(child.status)
  62. if (child.status !== 0) {
  63. error = child
  64. }
  65. try {
  66. fs.rmdirSync(tmpdir)
  67. } catch (ignore) {}
  68. if (error) {
  69. throw error
  70. }
  71. return child.stdout
  72. }
  73. function makeCommand (file, args) {
  74. var command, quote
  75. command = file
  76. if (args.length > 0) {
  77. for (var i in args) {
  78. command = command + ' '
  79. if (args[i][0] === '-') {
  80. command = command + args[i]
  81. } else {
  82. if (!quote) {
  83. command = command + '"'
  84. quote = true
  85. }
  86. command = command + args[i]
  87. if (quote) {
  88. if (args.length === (parseInt(i) + 1)) {
  89. command = command + '"'
  90. }
  91. }
  92. }
  93. }
  94. }
  95. return command
  96. }
  97. function determineOS () {
  98. var os = ''
  99. var tmpVar = ''
  100. if (process.env.OSTYPE) {
  101. tmpVar = process.env.OSTYPE
  102. } else if (process.env.OS) {
  103. tmpVar = process.env.OS
  104. } else {
  105. // default is linux
  106. tmpVar = 'linux'
  107. }
  108. if (startsWith(tmpVar, 'linux')) {
  109. os = 'linux'
  110. }
  111. if (startsWith(tmpVar, 'win')) {
  112. os = 'win'
  113. }
  114. return os
  115. }
  116. function unlinkFile (file) {
  117. fs.unlinkSync(file)
  118. }
  119. module.exports = processExecSync