Commit 05c3b55c authored by Ian McNally's avatar Ian McNally Committed by Ville Immonen
Browse files

add logging of existing default port process on start (#816)

* add logging of existing port process on start

* Move port process wording in start command on to next line

* Color the named processes as cyan in terminal output

* Add handling for multiple processes on a part

- With the currently process filtering, if multiple processes are returned as running on port 3000, this command would fail. This splits apart the process IDing and the process naming, to support multiple processes.
- One curious thing about the bash command to get processes, is that it'll include browsers with a window open on localhost:3000. May want to reconsider that.

* Add process directory to existing port warning

- also moved terminal coloring up, when getting the process, to be able to distinguish the process command from the directory

* Change output color to all cyan, except "in"

* Rename getProcessNameOnPort -> getProcessForPort

- better reflects its broadened scope (both command and directory)

*...
parent 9c45b252
No related merge requests found
Showing with 83 additions and 2 deletions
+83 -2
...@@ -142,6 +142,22 @@ compiler.plugin('done', function(stats) { ...@@ -142,6 +142,22 @@ compiler.plugin('done', function(stats) {
}); });
``` ```
#### `getProcessForPort(port: number): string`
Finds the currently running process on `port`.
Returns a string containing the name and directory, e.g.,
```
create-react-app
in /Users/developer/create-react-app
```
```js
var getProcessForPort = require('react-dev-utils/getProcessForPort');
getProcessForPort(3000);
```
#### `openBrowser(url: string): boolean` #### `openBrowser(url: string): boolean`
Attempts to open the browser with a given URL. Attempts to open the browser with a given URL.
......
var chalk = require('chalk');
var execSync = require('child_process').execSync;
var path = require('path');
var execOptions = {
encoding: 'utf8',
stdio: [
'pipe', // stdin (default)
'pipe', // stdout (default)
'ignore' //stderr
]
};
function isProcessAReactApp(processCommand) {
return /^node .*react-scripts\/scripts\/start\.js\s?$/.test(processCommand);
}
function getProcessIdOnPort(port) {
return execSync('lsof -i:' + port + ' -P -t -sTCP:LISTEN', execOptions).trim();
}
function getPackageNameInDirectory(directory) {
var packagePath = path.join(directory.trim(), 'package.json');
try {
return require(packagePath).name;
} catch(e) {
return null;
}
}
function getProcessCommand(processId, processDirectory) {
var command = execSync('ps -o command -p ' + processId + ' | sed -n 2p', execOptions);
if (isProcessAReactApp(command)) {
const packageName = getPackageNameInDirectory(processDirectory);
return (packageName) ? packageName + '\n' : command;
} else {
return command;
}
}
function getDirectoryOfProcessById(processId) {
return execSync('lsof -p '+ processId + ' | grep cwd | awk \'{print $9}\'', execOptions).trim();
}
function getProcessForPort(port) {
try {
var processId = getProcessIdOnPort(port);
var directory = getDirectoryOfProcessById(processId);
var command = getProcessCommand(processId, directory);
return chalk.cyan(command) + chalk.blue(' in ') + chalk.cyan(directory);
} catch(e) {
return null;
}
}
module.exports = getProcessForPort;
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
"clearConsole.js", "clearConsole.js",
"checkRequiredFiles.js", "checkRequiredFiles.js",
"formatWebpackMessages.js", "formatWebpackMessages.js",
"getProcessForPort.js",
"InterpolateHtmlPlugin.js", "InterpolateHtmlPlugin.js",
"openChrome.applescript", "openChrome.applescript",
"openBrowser.js", "openBrowser.js",
......
...@@ -26,6 +26,7 @@ var detect = require('detect-port'); ...@@ -26,6 +26,7 @@ var detect = require('detect-port');
var clearConsole = require('react-dev-utils/clearConsole'); var clearConsole = require('react-dev-utils/clearConsole');
var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); var checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
var formatWebpackMessages = require('react-dev-utils/formatWebpackMessages'); var formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
var getProcessForPort = require('react-dev-utils/getProcessForPort');
var openBrowser = require('react-dev-utils/openBrowser'); var openBrowser = require('react-dev-utils/openBrowser');
var prompt = require('react-dev-utils/prompt'); var prompt = require('react-dev-utils/prompt');
var pathExists = require('path-exists'); var pathExists = require('path-exists');
...@@ -273,9 +274,11 @@ detect(DEFAULT_PORT).then(port => { ...@@ -273,9 +274,11 @@ detect(DEFAULT_PORT).then(port => {
} }
clearConsole(); clearConsole();
var existingProcess = getProcessForPort(DEFAULT_PORT);
var question = var question =
chalk.yellow('Something is already running on port ' + DEFAULT_PORT + '.') + chalk.yellow('Something is already running on port ' + DEFAULT_PORT + '.' +
'\n\nWould you like to run the app on another port instead?'; ((existingProcess) ? ' Probably:\n ' + existingProcess : '')) +
'\n\nWould you like to run the app on another port instead?';
prompt(question, true).then(shouldChangePort => { prompt(question, true).then(shouldChangePort => {
if (shouldChangePort) { if (shouldChangePort) {
......
Supports Markdown
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